angularjs - 即使在成功调用 api 后,.NET Core web api 也会出现 CORS 错误

标签 angularjs google-chrome asp.net-web-api asp.net-core cors

所以我有一个 Angular 4 的 Angular CLI 应用程序与一个新的 .NET Core API 项目对话。我的环境是 Windows 7,我组织中使用的标准浏览器是 IE 11(所以最终需要使用它,但是我想在 Chrome 或 FF 中开发,因为 TypeScript/.map 文件在 Windows 7 上不起作用)。这是一个内部 Web 应用程序,我们需要使用 Windows 身份验证。我使用 Visual Studio 2017 Community 创建了 .NET Core 应用。

TL;DR 我的问题是我在 Chrome 和 FF 中不断收到 CORS 错误,即使在访问 api 并成功从后端返回数据之后也是如此。奇怪的是,当我在 .NET 端启用 CORS 时,Chrome 和 FF 成功调用了 api。当我尝试启用 CORS Chrome 或 FF 时,根本不要点击 api。在任何一种情况下,客户端代码都会调用错误处理程序,而不管它是否可以连接到 api。

这是我尝试过的 .NET 代码(尽管 Chrome 和 FF 都调用了没有这个的 api)。我在 Startup.cs\ConfigureSevices 中使用 AllowAnyOrigin 创建了一个 CORS 策略,还尝试了特定的“http://localhost:4200”url(应用运行的本地服务器)。还有 AllowAnyMethod 和 AllowAnyHeader 的各种组合。

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("MyPolicy",
            builder => 
            {
                builder.WithOrigins("http://localhost:4200")
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials();
            });
        });

    //...
}

我在 Startup.cs\Configure 中全局添加了 CORS 策略。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors("MyPolicy");

    // ...
}

我还尝试使用 [EnableCors] 将其作为属性直接添加到 Controller

[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class CustomerController : Controller

这是 Controller 上的方法:

// GET: api/customer/id
//[Authorize]
//[EnableCors("MyPolicy")]
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
    var customer = await _customerService.GetAsync(id);
    if (customer == null)
    {
        return NotFound();
    }

    string msJson = JsonConvert.SerializeObject(customer, 
        JsonCustomSettings.CustomJsonSettings);

    return Ok(msJson);
}

我还读到我需要将 withCredentials 选项添加到 Angular 中的 api 调用 - 这是 Angular 代码:

getContent(Id: number): Promise<Client[]> {
    const headers = new Headers({'Content-Type': 'application/json'});
    const options = new RequestOptions({ headers: headers, withCredentials: true });
    console.debug('In getContent:' + id);

    return this.http.get("http://localhost:13751/api/customer/"+id, options)
        .toPromise()
        .then(res => this.extractData(res))
        .catch(this.handleError);
}

结果:

在 Chrome 和 FF 中,“this.handleError”总是被调用。正如我所说,当我从 api 中删除 CORS 设置时,Chrome 和 FF 都会调用 api 并成功返回数据。

当我在 Startup.cs 和/或 Controller 的 .NET 端添加任何 CORS 选项并在 Controller 代码中放置一个断点时:

  • 在 IE 11 中没有错误(但是我遇到了其他 TypeScript 错误并且由于 Windows 7 上缺少 .map 文件而无法调试)
  • Chrome 或 FF 根本不访问 api,它们都返回 CORS 错误(错误见下文):

当我在 api 端禁用所有 CORS 设置时:

  • 在 IE 11 中没有错误
  • Chrome 和 FF 都命中了 api,数据从我的服务返回。然而,“this.handleError”总是被调用,当调用返回时,我在浏览器/TS 代码中收到 CORS 错误:

====

Chrome 错误:

XMLHttpRequest 无法加载 http://localhost:13751/api/customer/2518 .对预检请求的响应未通过访问控制检查:当凭据标志为真时,不能在“Access-Control-Allow-Origin” header 中使用通配符“*”。产地' http://localhost:4200 ' 因此不允许访问。 XMLHttpRequest 的凭据模式由 withCredentials 属性控制。

FF 错误:

跨源请求被阻止:同源策略不允许读取位于 http://localhost:13751/api/customer/2518 的远程资源. (原因:缺少 CORS header “Access-Control-Allow-Origin”) 跨源请求被阻止:同源策略不允许在 http://localhost:13751/api/customer/2518 读取远程资源. (原因:CORS 请求失败)。

====

所以我真的不明白为什么当我可以单步执行 api 端的代码并将数据返回给客户端时,为什么我在 Chrome 和 FF 中收到 CORS 错误。 (我也有适用于 Chrome 的“Allow-Control-Allow-Origin”插件,但这似乎没有什么区别)。

如果有人能阐明这一点,那就太好了。

最佳答案

您是否将“Access-Control-Allow-Origin” header 设置为 api 响应?

如果没有,这里有一个方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors("MyPolicy");

    // ... add api and other stuff

    //Add a middleware which sets the header on the response
    app.Use(async (context, next) =>
    {
        // Add Header
        context.Response.Headers["Access-Control-Allow-Origin"] = "*";

        // Call next middleware
        await next.Invoke();
    });
}

关于angularjs - 即使在成功调用 api 后,.NET Core web api 也会出现 CORS 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44883390/

相关文章:

javascript - 仅当选中复选框时才从 ng-repeat 中删除元素并控制台删除的值

javascript - 从查询字符串中获取数据

javascript - AngularJS google图表动态数据

c# - 如何使用angularjs在c#中调用API

ASP.NET Web API v2 并使用 ELMAH 记录所有错误/异常

asp.net-mvc - 包装 IHttpActionResult - 通用解决方案

JavaScript window.showModalDialog() 无法在 Chrome 上运行

javascript - 如何确保 Chrome 上的 HTML 视频自动播放脚本能够正常工作?

javascript - 我可以强制浏览器在继续执行 javascript 之前呈现出 DOM 更改吗?

c# - 等待ElasticSearch启动并运行