Flutter无法连接本地ASP.NET Core API获取数据问题求助
Flutter对接ASP.NET Core Web API时
snapshot.hasData返回false的排查方案 一、先确认你的ASP.NET Core API本身是否正常响应
直接用Postman、浏览器或者curl访问API接口,重点检查:
- 响应状态码:必须是
200 OK。如果是404(路径错误)、500(服务器内部错误)、401/403(权限问题),Flutter的HTTP请求会判定为失败,snapshot不会生成有效数据。 - 响应JSON格式:必须和你Flutter端的
Personel模型结构完全匹配。比如API返回的是纯数组[{"Id":1,"Name":"张三"},...],还是嵌套在包装对象里(比如{"data": [...], "code":200})——后者需要修改Flutter的解析逻辑。 - 跨域配置:ASP.NET Core默认不允许跨域请求,移动端(模拟器/真机)访问本地API会被拦截。在
Program.cs里添加跨域配置:var builder = WebApplication.CreateBuilder(args); // 添加跨域策略 builder.Services.AddCors(options => { options.AddPolicy("AllowAll", policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); // ... 其他服务配置 var app = builder.Build(); // 必须在UseRouting和UseAuthorization之前启用CORS app.UseCors("AllowAll"); app.UseAuthorization(); // ... 其他中间件
二、检查Flutter API服务的请求与解析逻辑
1. 请求基础信息是否正确
确保请求方法(GET/POST)、URL路径和你的API完全一致,比如API控制器路由是[Route("api/[controller]")],那URL应该是http://你的IP:端口/api/personels,不要拼写错误。
2. 解析逻辑匹配API返回格式
如果API返回纯JSON数组,解析代码应该是:
Future<List<Personel>> fetchPersonels() async { final response = await http.get(Uri.parse('你的API地址')); if (response.statusCode == 200) { final List<dynamic> jsonArray = json.decode(response.body); return jsonArray.map((item) => Personel.fromJson(item)).toList(); } else { throw Exception('加载失败:${response.statusCode}'); } }
如果API返回带包装的JSON对象(比如{"data": [...], "msg":"success"}),要先提取data字段:
Future<List<Personel>> fetchPersonels() async { final response = await http.get(Uri.parse('你的API地址')); if (response.statusCode == 200) { final Map<String, dynamic> responseMap = json.decode(response.body); final List<dynamic> jsonArray = responseMap['data']; return jsonArray.map((item) => Personel.fromJson(item)).toList(); } else { throw Exception('加载失败:${response.statusCode}'); } }
3. 打印请求详情排查错误
在API服务里添加日志,看实际请求的响应内容:
Future<List<Personel>> fetchPersonels() async { try { final response = await http.get(Uri.parse('你的API地址')); print('状态码:${response.statusCode}'); print('响应体:${response.body}'); if (response.statusCode == 200) { // 解析逻辑 } else { throw Exception('状态码异常:${response.statusCode}'); } } catch (e) { print('请求错误:$e'); rethrow; } }
通过控制台输出,就能直接定位是请求失败、JSON格式不对还是解析出错。
三、检查Personel模型的序列化/反序列化匹配
C#默认序列化出来的JSON字段是首字母大写(比如Id、Name),而Flutter模型如果用小驼峰(id、name),会导致解析失败,生成空数据或抛出异常。
正确的模型对应示例:
C#模型:
public class Personel { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
Flutter模型:
class Personel { final int id; final String name; final int age; Personel({required this.id, required this.name, required this.age}); factory Personel.fromJson(Map<String, dynamic> json) { return Personel( id: json['Id'], // 对应C#的Id字段(大写I) name: json['Name'], // 对应C#的Name字段(大写N) age: json['Age'], // 对应C#的Age字段(大写A) ); } }
如果想统一用小驼峰,可以在ASP.NET Core里配置JSON序列化规则:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; });
这样API返回的JSON字段就是小驼峰(id、name),Flutter模型就可以用对应的小驼峰字段解析。
四、完善Flutter首页的FutureBuilder错误处理
在FutureBuilder里添加错误状态的显示,能直接看到具体错误原因:
FutureBuilder<List<Personel>>( future: fetchPersonels(), builder: (context, snapshot) { if (snapshot.hasError) { // 显示错误信息 return Center(child: Text('加载失败:${snapshot.error}')); } if (snapshot.hasData) { // 数据不为空才渲染列表 if (snapshot.data!.isEmpty) { return Center(child: Text('暂无数据')); } return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { final person = snapshot.data![index]; return ListTile(title: Text(person.name)); }, ); } // 加载中状态 return Center(child: CircularProgressIndicator()); }, )
内容的提问来源于stack exchange,提问作者erenkahram4n
相关产品推荐
相关产品推荐

