【问题标题】:Angular / Web API unable to communicate on endpointAngular / Web API 无法在端点上通信
【发布时间】:2019-01-24 14:38:55
【问题描述】:

我遇到了一个问题,Angular 无法在 3 个端点中的 2 个端点上发出成功的请求,但我已确认所有与邮递员的工作,并且代理正在成功路由呼叫。 Chrome - 网络选项卡显示“已阻止:其他”,并且“ng serve”的输出不表示任何与代理有关的内容。我的角度服务和/或服务器端控制器有问题吗?

控制器

[Route("api/[controller]")]
[ApiController]
public class AffiliationController : ControllerBase
{
    public AffiliationController(
        IQueryHandler<GetAffiliationsQuery, IQueryable<Affiliation>> getAffiliationsQuery,
        ICommandHandler<ToggleAffiliationExclusionCommand> toggleAffiliationExclusionsCommand)
    {
        _getAffiliationsQuery = getAffiliationsQuery ?? throw new ArgumentNullException(nameof(getAffiliationsQuery));
        _toggleAffiliationExclusionsCommand = toggleAffiliationExclusionsCommand ?? throw new ArgumentNullException(nameof(toggleAffiliationExclusionsCommand));
    }

    private readonly IQueryHandler<GetAffiliationsQuery, IQueryable<Affiliation>> _getAffiliationsQuery;
    private readonly ICommandHandler<ToggleAffiliationExclusionCommand> _toggleAffiliationExclusionsCommand;

    // Successfully Called
    [HttpGet]
    public async Task<ActionResult<PaginationResult<Affiliation>>> GetAffiliations([FromQuery] PaginationModel model)
    {
        var affiliations = await _getAffiliationsQuery.Handle(new GetAffiliationsQuery())                                                            
                                               .PaginateAsync(model.PageIndex,                                                                            
                                                              model.PageSize);
        return affiliations;
    }

    // Not reached via Angular       
    [HttpGet("{id}")]
    public async Task<ActionResult<Affiliation>> Foo(int id)
    {
        var target = await _getAffiliationsQuery.Handle(new GetAffiliationsQuery())
                                                .SingleOrDefaultAsync(afn => afn.Id == id);
        if (target == null)
        {
            return NotFound();
        }
        await _toggleAffiliationExclusionsCommand.HandleAsync(new ToggleAffiliationExclusionCommand(id));
        return target;
    }

}

角度服务

export class AffiliationService {
  private readonly apiUrl = 'api/affiliation';

  constructor(
    private http: HttpClient
  ) { }

  public get(model: PaginationQuery): Observable<PaginationResult<Affiliation>> {
    // Works just fine
    return this.http
      .get<PaginationResult<Affiliation>>(`${this.apiUrl}`, { params: UtilsService.buildQueryParams(model) })
      .pipe(
        catchError(this.handleError)
      );
  }

  public toggle(affiliation: Affiliation) {
  // Does not work unless I pass the 'id' as a query string parameter instead of a route parameter
    return this.http
      .get(`${this.apiUrl}/${affiliation.id}`)
      .pipe(
        catchError(this.handleError)
      );
  }

  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      console.error('An error occurred:', error.error.message);
    } else {
      console.error(`Backend returned code ${error.status}, body was:`);
      console.error(error.error);
    }
    return throwError('Something bad happened; please try again later.');
  }
}

proxy.conf.json

{
  "/api/*": {
    "target": "http://localhost:5000",
    "secure": false,
    "logLevel": "debug"
  }
}

NG 服务输出

注意

将'toggle'功能改成如下即可成功到达终点。但我不明白为什么这可以通过其他方式起作用,因为我可以通过 Postman 使用路由参数方法调用端点

  public toggle(affiliation: Affiliation) {
    return this.http
      .get(`${this.apiUrl}`, { params: UtilsService.buildQueryParams({ id: affiliation.id }) })
      .pipe(
        catchError(this.handleError)
      );
  }

【问题讨论】:

  • 我认为它在您的后端,因为您收到所有请求并通过客户端处理它。您是否尝试记录您的 http get 方法?看看你是否甚至输入了该功能?或者它之前抛出
  • Chrome 图像显示 API 调用被发送到端口 4200,而不是端口 5000(见红色 GET 行)。不幸的是,不知道如何解决这个问题(低于零的 Angular 知识)。在相对 URL 前面加上正确的架构+域+端口可能会有所帮助。
  • 我在客户端收到的唯一输出来自上面的“ng serve output”屏幕截图。就好像代理甚至没有收到重新路由到端口 5000 以调用“Foo”端点的调用。 @PeterB 我对 angular-cli 提供的代理功能还比较陌生,但控制台输出似乎表明它已成功将调用路由到后端的端口 5000。我没有启用 CORS,所以如果它实际上在端口 4200 上进行,我预计会在第一次调用时遇到错误。
  • 为了排除问题,尝试将这两种方法的 API 路由更改为完全不同的其他方式(例如,/api/test1 和 /api/test2)。我怀疑这个问题与后端的路由图有关。

标签: c# angular .net-core asp.net-core-webapi asp.net-web-api-routing


【解决方案1】:

这看起来像是一个 CORS 问题。

如果你想在不使用插件的情况下解决这个问题,你可以使用 WebApi Cors 包。

如果使用 C# ASP.NET CORE 项目:

参考下页开启CORS,请求可以 叫。 https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1

如果使用 C# WebAPI 项目:

运行以下命令为 WebApi 安装 CORS 包:

Install-Package Microsoft.AspNet.WebApi.Cors

那么你可以如下使用它:

using System.Web.Http;
namespace WebService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // New code
            config.EnableCors();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

并参阅以下 URL 以获取完整的 microsoft 指南:

https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api

【讨论】:

  • 对于“ng serve”的输出,我从代理收到以下信息。它似乎成功地路由了第一个呼叫,但与失败的呼叫无关。 [HPM] GET /api/affiliation?pageIndex=1&pageSize=10 -> localhost:5000
  • 我假设的第一个属于 zone.js 的角度处理,如果你查看它的响应,我相信你不会从你的 WebApi 中看到任何有意义的东西,如果有的话。它并没有真正与您的服务器通信。
  • Angular-cli 代理是否应该避免任何 CORS 问题,因为它实际上将请求路由到正确的 url?
  • 从看起来这可以添加的最大值是允许客户端尝试处理“api/”之后的任何路由。请注意,您的 Angular 项目正在节点服务器和端口 5000 上运行。而 C# 项目正在随机端口上的 iisexpress 上运行。这是绝对正常的,但这意味着客户端必须使用完整的 url 与服务器通信,包括正确的域和端口。
  • Angular 项目在端口 4200 上运行。.Net Core API 在端口 5000 上运行
猜你喜欢
  • 2019-02-01
  • 2021-12-07
  • 2023-03-23
  • 1970-01-01
  • 2013-04-20
  • 2018-12-06
  • 1970-01-01
  • 2020-04-18
  • 2016-02-15
相关资源
最近更新 更多