You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asp.Net Core+Angular4调用接口遇NodeInvocationException错误求助

问题分析与修复:Angular 4 + ASP.NET Core 菜单接口调用JSON解析错误

问题背景

你正在使用ASP.NET Core作为后端、Angular 4作为前端开发项目,通过ProjectRoleService调用后端MenuController的接口时,遇到了Unexpected end of JSON input错误,错误栈指向前端尝试解析JSON时失败。

前端服务代码(ProjectRoleService)

import { Injectable, Inject } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import { Http } from '@angular/http'; 
import 'rxjs/Rx'; 

@Injectable() 
export class ProjectRoleService { 
  _serverURL: string; 
  constructor(private _http: Http) { 
    this._serverURL = "http://localhost:8080/api"; 
  } 

  getMenuDetails(roleName: string) { 
    let _url = this._serverURL + "/Menu/GetMenuDetails?roleName=" + roleName; 
    return new Promise((resolve, reject) => { 
      this._http.get(_url) 
        .map(res => res.json()) 
        .catch((error: any) => { 
          console.error(error); 
          reject(error); 
          return Observable.throw(error.json().error || 'Server error'); 
        }) 
        .subscribe((data) => { 
          resolve(data); 
        }); 
    }); 
  } 
}

后端控制器代码(MenuController)

public class MenuController : ApiController { 
  /// <summary> 
  /// Get Menu Details by logged in user role 
  /// </summary> 
  /// <param name="email ID"></param> 
  /// <returns></returns> 
  [Microsoft.AspNetCore.Mvc.HttpGet] 
  public HttpResponseMessage GetMenuDetails(string roleName) { 
    HttpResponseMessage httpResponseMessage = null; 
    try { 
      httpResponseMessage = Request.CreateResponse(new Menu().GetMenuDetails(roleName)); 
    } catch (Exception ex) { 
      throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { 
        Content = new StringContent(ex.Message), 
        ReasonPhrase = "Warning" 
      }); 
    } 
    return httpResponseMessage; 
  } 
}

错误信息

NodeInvocationException: Unexpected end of JSON input 
SyntaxError: Unexpected end of JSON input 
at JSON.parse (<anonymous>) 
at Response.module.exports.Body.json (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:71887:25) 
at CatchSubscriber.selector (E:\AngularProject\NodeUI\ClientApp\dist\main-server.js:19325:96) 
at CatchSubscriber.module.exports.CatchSubscriber.error (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:91048:31) 
at MapSubscriber.module.exports.Subscriber._error (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:10724:26) 
at MapSubscriber.module.exports.Subscriber.error (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:10698:18) 
at ZoneTask.onComplete [as callback] (E:\AngularProject\NodeUI\ClientApp\dist\main-server.js:4454:30) 
at ZoneDelegate.module.exports.ZoneDelegate.invokeTask (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:85819:31) 
at Object.onInvokeTask (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:14821:37) 
at ZoneDelegate.module.exports.ZoneDelegate.invokeTask (E:\AngularProject\NodeUI\ClientApp\dist\vendor.js:85818:36)

错误原因分析

这个错误的核心是前端尝试解析一个空或无效的JSON响应,主要由以下几个问题导致:

  1. 后端返回类型不匹配ASP.NET Core规范:你在ASP.NET Core中使用了旧的HttpResponseMessage(这是Web API 2的用法),而ASP.NET Core MVC推荐使用IActionResult作为返回类型,直接使用HttpResponseMessage可能导致响应没有正确序列化JSON,甚至返回空内容。
  2. 前端Promise与Observable混用:Angular的Http模块本身返回Observable,你手动包装成Promise的方式存在冗余,且错误处理逻辑可能在响应为空时触发解析失败。
  3. 潜在的后端返回空内容:如果new Menu().GetMenuDetails(roleName)返回null或未正确初始化的对象,后端可能返回空响应,导致前端res.json()解析失败。

具体修复步骤

1. 修复后端Controller的返回类型

将HttpResponseMessage替换为ASP.NET Core标准的IActionResult,确保响应正确序列化:

using Microsoft.AspNetCore.Mvc; // 确保引入这个命名空间

[Route("api/[controller]")] // 添加路由特性,确保接口路径正确
public class MenuController : ControllerBase { // 继承ControllerBase而不是ApiController(ASP.NET Core中推荐)
  /// <summary> 
  /// Get Menu Details by logged in user role 
  /// </summary> 
  /// <param name="roleName"></param> 
  /// <returns></returns> 
  [HttpGet("GetMenuDetails")]
  public IActionResult GetMenuDetails(string roleName) { 
    try { 
      var menuDetails = new Menu().GetMenuDetails(roleName);
      // 如果返回结果为空,返回空数组或默认值,避免空响应
      if (menuDetails == null)
      {
          return Ok(new List<Menu>()); // 假设Menu是集合类型,根据实际情况调整
      }
      return Ok(menuDetails); // Ok()会自动序列化对象为JSON
    } catch (Exception ex) { 
      return StatusCode(StatusCodes.Status500InternalServerError, new { 
        Message = ex.Message,
        ReasonPhrase = "Warning"
      }); 
    } 
  } 
}

2. 优化前端Service代码

去掉冗余的Promise包装,直接使用Observable,同时添加响应内容检查:

import { Injectable } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import { Http, Response } from '@angular/http'; 
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable() 
export class ProjectRoleService { 
  private _serverURL = "http://localhost:8080/api"; 

  constructor(private _http: Http) { } 

  getMenuDetails(roleName: string): Observable<any> { 
    const _url = `${this._serverURL}/Menu/GetMenuDetails?roleName=${encodeURIComponent(roleName)}`;
    // 使用encodeURIComponent处理特殊字符,避免URL拼接错误
    
    return this._http.get(_url)
      .map((res: Response) => {
        // 检查响应是否有内容
        if (res.status === 204 || res.text().trim() === '') {
          return []; // 返回空数组作为默认值
        }
        return res.json();
      })
      .catch((error: any) => {
        console.error('API调用错误:', error);
        // 处理错误信息,避免解析错误的JSON
        const errorMsg = error.json ? error.json().Message || 'Server error' : error.message;
        return Observable.throw(errorMsg);
      });
  } 
}

如果你仍然需要使用Promise,可以在调用处用.toPromise()转换,比如:this.projectRoleService.getMenuDetails('admin').toPromise().then(...)

3. 验证后端接口有效性

先直接在浏览器或Postman中访问接口:http://localhost:8080/api/Menu/GetMenuDetails?roleName=你的角色名,检查返回的内容:

  • 如果返回有效的JSON数组/对象,说明后端修复成功;
  • 如果返回错误或空内容,检查Menu.GetMenuDetails(roleName)的逻辑,确保它返回正确的对象集合。

4. 检查CORS配置(可选)

如果前端运行在不同端口(比如Angular默认4200),需要在ASP.NET Core中配置CORS,允许前端域名访问:
在Startup.cs的ConfigureServices中添加:

services.AddCors(options =>
{
    options.AddPolicy("AllowLocalAngular",
        policy => policy.WithOrigins("http://localhost:4200") // 你的Angular地址
                        .AllowAnyHeader()
                        .AllowAnyMethod());
});

然后在Configure中启用:

app.UseCors("AllowLocalAngular");

总结

最核心的问题是后端使用了不兼容ASP.NET Core的返回类型,导致响应没有正确序列化JSON。通过切换到IActionResult、优化前端响应处理,应该能解决这个JSON解析错误。

内容的提问来源于stack exchange,提问作者CPK_2011

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:16:00