Angular 4 / .NET Core 2 Web API:CORS问题

时间:2018-03-26 14:23:41

标签: angular api cors .net-core

所以我有一个前端Angular应用程序,我填写一个小表单,并希望将数据发送到我的Web API,它也运行在localhost上。我的Angular应用程序在http://localhost:4200/上运行,我的网络API在https://localhost:44302/api/input上运行。

在表单提交时,将调用以下方法:

public uploadFormData(): void {
    const form = $('#inputForm')[0];
    const files = ($('#fileUpload') as any);
    const formData = new FormData();
    const file = files[0];

    formData.append('tenant', form[0].value);
    formData.append('title', form[1].value);
    formData.append('file', file, file.name);
    this.uploadService.uploadForm(formData)
      .subscribe(res => this.fileUploaded(res));
  }

  private fileUploaded(data: any): void {
    $('#message').html('Response: 200 OK !');
  }  

这将转到我的服务,如下所示:

public uploadForm(formdata: any) {
    const url = 'https://localhost:44302/api/input';
    const headers = new Headers({'encrypt': 'multipart/form-data'});
    const options = new RequestOptions({ headers: headers });

    return this.http.post(url, formdata, options)
      .catch(this.errorHandler);
  }

  private errorHandler(error: Response) {
    return Observable.throw(error || 'Some error on server occured: ' + error);
  }  

如果我删除标题&选项(以及我的http.post中的选项),最终结果是相同的:将抛出500服务器错误

"No 'Access-Control-Allow-Origin' header is present on the requested 
resource. Origin 'http://localhost:4200' is therefore not allowed access. 
The response had HTTP status code 500."  

所以在我的服务器端,我有一个在localhost上运行的.NET Core 2 Web API。这是我的Startcup.cs文件,所以你可以看到我配置了CORS:

// This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddAzureAdBearer(options => Configuration.Bind("AzureAd", options));

            services.AddMvc();

            services.AddCors();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors(builder =>
                builder.WithOrigins("http://localhost:4200")
                //builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());

            app.UseAuthentication();
            app.UseMvc();
        }  

在这里,您可以找到接受输入的控制器代码:

// POST api/input
    [HttpPost]
    public IActionResult Post(FormCollection data)
    {
        var inputdata = data;
        //var test = JsonConvert.DeserializeObject<SPInputObject>(data);

        return Ok("POST all good");
    }  

我甚至不知道&#34; FormCollection数据&#34;是正确的参数,因为由于这些CORS问题我无法进入我的web api。

所以有人可以看到可能出现的问题吗?

编辑:在服务器500错误之前,您可以在此处查看Chrome开发工具中的响应/请求标头:

enter image description here

这是我在500服务器错误后看到的内容:

enter image description here

2 个答案:

答案 0 :(得分:0)

您需要安装一个nuget软件包:“ Microsoft.AspNet.WebApi.Cors”, 并将其添加到类启动中:

            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }

            public IConfiguration Configuration { get; }

            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc();
                services.AddCors(options => options.AddPolicy("AllowAll", builder =>
                {
                    builder.AllowAnyOrigin();
                    builder.AllowAnyHeader();
                    builder.AllowAnyMethod();
                    builder.AllowCredentials();
                }));
            }

            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                app.UseCors("AllowAll"); //<===
                app.UseMvc();
            }

添加到您的控制器

[EnableCors(origins: "http://localhost:4200", headers: "*", methods: "*")]

在标题中(有角):

              const httpOptions = {
                headers: new HttpHeaders({
                  'Access-Control-Allow-Origin': '*',
                  'Access-Control-Allow-Headers': 'Content-Type, Origin , Access-Control-* , X-Requested-With, Accept',
                  'Content-Type':  'application/json,charset=utf-8',
                  'Accept': 'application/json',
                  'Allow' : 'GET, POST, PUT, DELETE, OPTIONS, HEAD'
                })
              };

最后在浏览器中安装Allow-Control-Allow-Origin

答案 1 :(得分:0)

我认为您需要根据this博客文章在app.UseMvc()行代码之前提及app.UseCors()。

准确地说:

services.AddCors(feature => {
                feature.AddPolicy(
                    "GlobalCorsPolicy",
                    builder => builder
                                    .SetIsOriginAllowed((host) => true)
                                    .AllowAnyHeader()
                                    .AllowAnyMethod()
                                    .AllowAnyOrigin()
                                    .AllowCredentials()
                                );
            });

以上所述,这条线确实付出了高昂的代价。

  

.SetIsOriginAllowed((host)=> true)

然后,您必须在控制器中显式设置EnableCors(“ GlobalCorsPolicy”)]作为装饰属性。 关于是否要在全球范围内添加,为什么要添加,有很多讨论和争论,但是我的解决方案实际上是解决了这个问题。

并且无需添加任何浏览器的Allow-Control-Allow-Origin插件,如果您在代码中添加了这些插件,它将可以正常工作。

经过全部地狱尝试后,我得以通过。

This帖子也对我有帮助。我相信,如果您按照这些步骤进行操作,并且只需进行几次迭代就可以自己学习/理解CORS的工作方式以及在.net core中的使用方式,则可以解决此问题。当然,它与.net Web API(fx)中的易用性不同。