React Native调用.NET Core 6 API报Network request failed
Expo iOS模拟器调用.NET Core 6接口报Network request failed解决方案
问题背景
React Native初学者从后端API拉取数据时持续遇到Network request failed报错,尝试多种排查方式均未解决。
当前技术环境:
- 后端框架:.NET Core 6
- 开发工具:Visual Studio Code
- 客户端运行环境:Expo启动iOS模拟器
现有代码
React端代码
import { StatusBar } from "expo-status-bar"; import { useState } from "react"; import { StyleSheet, Text, View } from "react-native"; import Home from "./screens/Home"; export default function App() { const [weather, setWeather] = useState("Loading.."); const getWeather = async () => { var res = await fetch("https://192.168.1.205:5001/WeatherForecast", { method: "GET", }) .then((response) => response.json()) .then((responseJson) => { alert("Succ"); // Handle response here }) .catch((error) => { console.error(error); alert(error); }); }; // return <Home /> getWeather(); return ( <View> <Text></Text> <Text style={{ paddingTop: 50, marginLeft: 30 }}>{weather}</Text> </View> ); }
后端Controller代码
using Microsoft.AspNetCore.Mvc; namespace RestaurantAPI.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } } }
后端Program.cs配置代码
var builder = WebApplication.CreateBuilder(args); var CorsPolicy = "_myAllowSpecificOrigins"; // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddCors(options => { options.AddPolicy(name: CorsPolicy, b => { b.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin(); }); }); builder.WebHost.UseKestrel(); builder.WebHost.UseUrls("http://localhost:5001", "https://192.168.1.205:5001"); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } //app.UseHttpsRedirection(); by waleed app.UseCors(CorsPolicy); app.UseAuthorization(); app.MapControllers(); app.Run();
问题现象
- Postman调用
https://192.168.1.205:5001/WeatherForecast接口可正常获取返回数据 - VS Code中通过React Native发起相同请求时,抛出Network request failed错误
已尝试排查方案
- 尝试使用localhost作为API访问地址
- 尝试使用局域网IP访问后端服务
- 更换服务监听端口为5001
- 在Program.cs中配置全放行的CorsPolicy跨域策略
以上方案均未解决问题。
问题根因&解决步骤
报错和跨域、端口配置无关,核心是三个容易踩的坑:iOS模拟器的地址映射规则、iOS对自签名HTTPS证书的拦截、React错误的请求触发时机。按以下步骤修改即可解决:
第一步:改用HTTP协议+局域网IP访问本地接口
iOS模拟器里的localhost指向模拟器自身,不是运行后端的宿主机,直接写localhost永远访问不到宿主机服务;另外iOS默认拦截不受信任的自签名HTTPS证书,.NET Core本地启动的HTTPS端点用的是本地开发自签名证书,iOS模拟器不会信任这个证书会直接阻断请求,Postman默认跳过证书校验所以能正常访问。
修改Program.cs里的UseUrls配置,让Kestrel同时监听HTTP的局域网地址:
builder.WebHost.UseUrls("http://localhost:5000", "http://192.168.1.205:5000", "https://192.168.1.205:5001");
把React端的请求地址改成对应HTTP的局域网地址:
const res = await fetch("http://192.168.1.205:5000/WeatherForecast", { method: "GET", })
开发阶段不需要用HTTPS调本地接口,直接走HTTP就能避开自签名证书的信任问题。如果必须用HTTPS,需要在iOS项目里配置ATS例外,把局域网IP加入允许列表,同时手动信任开发证书,流程非常繁琐,开发阶段完全没必要。
第二步:把接口请求放到useEffect副作用里执行
不要直接在组件函数体里调用接口,会导致重复渲染、重复触发请求,Expo的fetch在组件首次渲染同步触发时也会偶现拦截问题。修改React端的App组件,引入useEffect包裹请求逻辑:
import { StatusBar } from "expo-status-bar"; import { useState, useEffect } from "react"; import { StyleSheet, Text, View } from "react-native"; import Home from "./screens/Home"; export default function App() { const [weather, setWeather] = useState("Loading.."); const getWeather = async () => { try { const res = await fetch("http://192.168.1.205:5000/WeatherForecast", { method: "GET", }) const data = await res.json(); setWeather(JSON.stringify(data)); alert("请求成功"); } catch (error) { console.error(error); alert(`请求失败: ${error.message}`); } }; useEffect(() => { getWeather(); }, []); return ( <View> <Text></Text> <Text style={{ paddingTop: 50, marginLeft: 30 }}>{weather}</Text> </View> ); }
第三步:放行本地防火墙端口
macOS系统防火墙默认会拦截外部对本地Kestrel服务的访问,打开系统设置-网络-防火墙,给dotnet进程放行入站连接,或者临时关闭防火墙测试。
改完之后重启后端服务,刷新Expo模拟器,就能正常拿到接口返回数据。
内容的提问来源于stack exchange,提问作者Waleed Abukatab
相关产品推荐
相关产品推荐

