React无法从Web API获取数据:问题排查与解决咨询
问题背景
我使用React v18.2.0和NextJS v13.3.0开发,Web API端代码如下:
Web API控制器代码
public List<ReturnDat> Get() { List<ReturnDat> lst = new List<ReturnDat>(); lst.Add(new ReturnDat() { ID = 1, Title = "Title -1 " }); return lst; }
实体类代码
public class ReturnDat { [DataMember(EmitDefaultValue = false)] public int ID { get; set; } [DataMember(EmitDefaultValue = false)] public string Title { get; set; } }
WebApiConfig配置
config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings .Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept", "text/html", StringComparison.InvariantCultureIgnoreCase, true, "application/json"));
React端代码
const[data,setData] = useState([]); const[num,setNum] = useState(1); const fetchData = async () => { const response = await fetch("https://localhost:44346/api/values/"); //https://swapi.dev/api/people/1/ const newData = await response.json(); }; useEffect(() =>{ fetchData(); });
问题现象
API已被调用并执行到返回语句,但React端提示TypeError: Failed to fetch。使用相同代码调用第三方API可正常工作,尝试过添加/移除[DataMember]、调整Web API的JSON格式化配置、修改返回类型,均无效。使用NextJS的getServerSideProps()可正常获取API数据。
问题原因与解决方案
核心原因
问题出在浏览器同源策略导致的CORS(跨域资源共享)拦截:
- 前端运行在NextJS开发服务器(默认端口localhost:3000),Web API运行在localhost:44346,属于不同端口,浏览器会阻止前端直接发起跨域请求。
getServerSideProps()是在服务器端发起请求,不受浏览器同源策略限制,因此能正常获取数据;而组件内的fetch是浏览器端发起,触发了CORS拦截。
解决方案
方案1:在Web API端配置CORS
- 安装Web API CORS包:
Install-Package Microsoft.AspNet.WebApi.Cors
- 在
WebApiConfig.cs中启用并配置CORS:
// 启用CORS config.EnableCors(); // 全局允许指定前端域名的跨域请求(开发环境可临时用*,生产环境必须指定具体域名) config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
- 给目标控制器添加CORS特性(如果未全局配置):
[EnableCors(origins: "http://localhost:3000", headers: "*", methods: "*")] public class ValuesController : ApiController { // 控制器代码 }
方案2:在NextJS中配置请求代理
利用NextJS的代理功能,将前端请求转发到Web API,绕过浏览器跨域限制:
- 在项目根目录创建
next.config.js:
/** @type {import('next').NextConfig} */ const nextConfig = { async rewrites() { return [ { source: '/api/:path*', destination: 'https://localhost:44346/api/:path*', }, ] }, } module.exports = nextConfig
- 修改React端的
fetch地址:
const response = await fetch("/api/values/");
- 重启NextJS开发服务器,代理自动生效。
额外注意事项
- 生产环境中CORS配置禁止使用
*允许所有来源,必须指定前端部署的具体域名,避免安全风险。 - 检查Web API的认证配置:你的
WebApiConfig中添加了HostAuthenticationFilter,需确认认证逻辑是否拦截了CORS预检请求(OPTIONS请求),必要时需放行OPTIONS请求。
内容的提问来源于stack exchange,提问作者Hasan Shouman
相关产品推荐
相关产品推荐

