【问题标题】:Unable to access the webapi from angular 8 application无法从 Angular 8 应用程序访问 webapi
【发布时间】:2019-12-25 03:33:36
【问题描述】:

我已经实现了一个 asp.net 核心 web api,并且端点似乎工作正常。我正在通过其本地网络服务器运行 webapi。我也可以通过邮递员访问 api。我已经实现了一个 Angular 8 应用程序。尝试访问 api 端点时出现未知错误。我最初认为这是 cors 问题并在我的控制器中启用了 cors,但仍然面临同样的问题。谁能告诉我可能是什么问题

webapi url 是 http://localhost:56676/api/customers,angular 应用程序 url 是 http://localhost:4200/customer

得到的错误信息是

从源“http://localhost:4200”对“http://localhost:56676/api/customers/”处的 XMLHttpRequest 的访问已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:没有“Access-Control-Allow-Origin”标头出现在请求的资源上。

角度代码

客户组件

ngOnInit() {
      this.customers$ = this.customerService.getCustomers()
          .pipe(
              catchError(err => {
                 this.errorMessage = err;
                 return EMPTY;
              })
          )
  }

客户界面

interface ICustomer {

        customerId : string;
        companyName : string;
        contactName : string;
        contactTitle : string;
        address : string;
        city : string;
        region : string;
        postalCode : string;
        country : string;
        phone : string;
        fax : string;

}

客户服务

export class CustomerService {

  constructor(private smartTrCommonService:  SmartTrCommonService) { }

  getCustomers() : Observable<ICustomer[]>{
    return this.smartTrCommonService.httpGet('/api/customers/');
  }
}

公共服务

export class SmartTrCommonService {

    webApplication = this.getApiLocation();

    private getApiLocation() {
        const port = location.port ? ':56676' : '';
        return location.protocol + '//' + location.hostname + port;
    }

    constructor(private httpClient: HttpClient) { }

    httpGet(url: string): Observable<any> {
        return this.httpClient.get(this.webApplication + url, httpPostOptions)
            .pipe(map((response: Response) => {
                return response;
            }), catchError(error => {
                this.onError(error);
                return Promise.reject(error);
            }));
    }
}

Asp.Net 核心

[EnableCors("AllowOrigin")]
    [Route("api/[controller]")]
    [ApiController]
    public class CustomersController : ControllerBase
    {

        ICustomerRepository _customersRepository;


        public CustomersController(ICustomerRepository customersRepository)
        {
            _customersRepository = customersRepository;
        }

        [HttpGet]
        [EnableCors("AllowOrigin")]
        public async Task<IActionResult> Get()
        {
            try
            {
                var customers = await _customersRepository.GetAllCustomers();
                if (customers == null)
                {
                    return NotFound();
                }

                return Ok(customers);
            }
            catch
            {
                return BadRequest();
            }
        }
}

startup.cs

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);


            services.AddSwaggerGen(c =>
            {

            });


            services.AddDbContext<NorthwindContext>(item => item.UseSqlServer(Configuration.GetConnectionString("NorthwindDBConnection")));
            services.AddCors(c =>
        {
            c.AddPolicy("AllowOrigin", options => options.WithOrigins("http://localhost:4200"));
        });

            var mappingConfig = new MapperConfiguration(mc =>
            {
                mc.AddProfile(new MappingProfile());
            });

            IMapper mapper = mappingConfig.CreateMapper();
            services.AddSingleton(mapper);



            services.AddScoped<ICustomerRepository, CustomerRepository>();
        }

        // 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();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
               app.UseCors(options => options.WithOrigins("http://localhost:4200"));
            app.UseCors("MyPolicy");
            app.UseHttpsRedirection();
            app.UseSwagger();
            app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "API name"); });
            app.UseMvc();
        }

更新的启动文件

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().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);


            services.AddSwaggerGen(c =>
            {

            });


            services.AddDbContext<NorthwindContext>(item => item.UseSqlServer(Configuration.GetConnectionString("NorthwindDBConnection")));

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

            var mappingConfig = new MapperConfiguration(mc =>
            {
                mc.AddProfile(new MappingProfile());
            });

            IMapper mapper = mappingConfig.CreateMapper();
            services.AddSingleton(mapper);



            services.AddScoped<ICustomerRepository, CustomerRepository>();
        }

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

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseCors("AllowOrigin");

            app.UseHttpsRedirection();
            app.UseSwagger();
            app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "API name"); });
            app.UseMvc();
        }
    }

【问题讨论】:

  • 你能分享你得到的错误信息吗
  • 肯定不是http://4200:locahost/,我想你的意思是http://locahost:4200/
  • 对不起,这就是我的意思。 localhost:4200/customer
  • 用错误信息更新了帖子
  • 作为旁注,两层服务,并返回一个通过管道连接到错误处理程序的服务,或者管道->映射->返回响应是非常 奇怪。我的意思是,我什至没有看到 .subscribe()... 它是您模板中的异步管道吗?我的 0.02 美元,我会保持简单:angular.io/guide/http

标签: angular asp.net-core asp.net-core-webapi


【解决方案1】:

尝试配置您的 CORS 策略,例如:

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

【讨论】:

  • @Tom 如何尝试与此解决方案集成:stackoverflow.com/a/42199758/10158551 并在您的配置方法中删除额外的app.UseCors(options =&gt; options.WithOrigins("http://localhost:4200")); 并使用app.UseCors("AllowOrigin"); 而不是app.UseCors("MyPolicy");
  • 我添加了该中间件并进行了您建议的更改。最大的改进是它现在正在使用 api 控制器方法,但最终失败并响应客户端对来自源“localhost:56676/api/customers”的 XMLHttpRequest 的响应被 CORS 策略阻止:没有“访问控制” -Allow-Origin' 标头出现在请求的资源上。
  • @Tom 很奇怪。似乎还有 CORS 问题...您需要凭据吗?如果不需要,您可以尝试删除 AllowCredentials() 并重试吗?什么是 httpPostOptions您的服务?您似乎在调用GET 方法?您可以在原始代码中向我们展示吗?
  • const httpPostOptions = { headers: new HttpHeaders( { 'Content-Type': 'application/json; charset=utf-8', }), withCredentials: true, }
  • @Tom 我从你编辑的代码中重现了这个问题,你需要删除 url 末尾的"/",所以使用builder.WithOrigins("http://localhost:4200")而不是builder.WithOrigins("http://localhost:4200/"),同时添加AllowCredentials()
【解决方案2】:

我认为您遇到了 CORS 错误:对于开发,您可以:

  • 在您的 API 中修复它(以接受您的主机/IP 地址)
  • 使用 CORS 插件

查看this

【讨论】:

  • 文章说 add_header 'Access-Control-Allow-Origin' 'localhost:4200' always; .我没有找到在哪里添加
猜你喜欢
  • 2018-04-27
  • 2020-01-27
  • 2019-09-16
  • 1970-01-01
  • 2018-11-27
  • 2023-03-17
  • 1970-01-01
  • 2015-02-06
  • 1970-01-01
相关资源
最近更新 更多