最近做一個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"} } }; }
結果: