最近做一个React的简单项目,需要调用WebApi接口,调用遇到了CORS跨域问题,特此记录一下:
简单的js页面如下:
import React, { Component } from 'react'; class App extends Component{ render(){ return( <ShoppingList name="Mark" /> ); } }; var REQUEST_URL = "https://localhost:44359/api/values"; class ShoppingList extends React.Component { constructor(props){ super(props); this.state={ error:null, isLoaded:false, items:[] } } componentDidMount(){ fetch(REQUEST_URL, { method: "GET", // *GET, POST, PUT, DELETE, etc. mode: 'cors' // no-cors, cors, *same-origin }) .then(res=>res.json()) .then( (result)=>{ this.setState({ isLoaded:true, items:result.items }); }, (error)=>{ this.setState({ isLoaded:true, error }) } ) } render() { const{error,isLoaded,items}=this.state; if(error){ return<div>Error:{error.message}</div> }else if(! isLoaded){ return <div>Loading...</div>; }else { return ( <ul> {items.map(item => ( <li key={item.id}> {item.id} {item.name} </li> ))} </ul> ); } } } export default App;
后端代码:
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values [HttpGet] public ActionResult<ItemsModel> Get() { return new ItemsModel { Items = new List<Item> { new Item{Id=1,Name="apple",Price = "5"}, new Item{Id=2,Name="banbana",Price = "3.5"} } }; }
调用的时候报错:Error:Failed to fetch
查看控制台报错:Failed to load https://localhost:44359/api/values: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
这是明显的跨域问题,一开始只是想着加个“Access-Control-Allow-Origin”的header给后台,就想着搜索如何添加这个头,结果方向是错的,搜到的结果都是不对(主要是版本陈旧)。后来想到这既然是跨域的问题,那就直接搜索.netcore 的WebApi如何支持跨域就好了(鄙视一下自己的记性,看过的东西都不知道深入理解一下,以至于用到的时候想不到走了好多弯路......),方向对了就很容易找到解决方案啦:
链接:https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-2.2
我选择的方案是:
使用属性启用 CORS
直接上代码(Startup文件中配置):
public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddDefaultPolicy( builder => { builder.WithOrigins("*") .AllowAnyHeader() .AllowAnyMethod(); }); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
然后应用一下默认属性即可:
[EnableCors] [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values [HttpGet] public ActionResult<ItemsModel> Get() { return new ItemsModel { Items = new List<Item> { new Item{Id=1,Name="apple",Price = "5"}, new Item{Id=2,Name="banbana",Price = "3.5"} } }; }
结果: