.NET MAUI中通过REST API获取新建Supplier的ID并关联SectionSupplier报错
问题排查:.NET MAUI创建Supplier关联Section时的异常与调试问题
核心问题
运行时抛出异常:No JSON Content found and type 'System.Int32' is not nullable . Path '', line 0, position 0,且调试无法进入RelayCommand。
问题分析与修复步骤
1. 反序列化异常根源:API返回内容不匹配
你在客户端代码里尝试把API返回的内容直接反序列化为int,但Supplier控制器的CreateSupplier方法返回的是完整的SupplierDto对象,不是单独的ID数值,这直接导致了反序列化失败。
错误代码:
var supplierIdJson = await response.Content.ReadAsStringAsync(); var newSupplierId = JsonConvert.DeserializeObject<int>(supplierIdJson);
修复方案:
先反序列化为SupplierDto,再提取Id属性:
var supplierResponse = await response.Content.ReadFromJsonAsync<SupplierDto>(); if (supplierResponse == null) { await Shell.Current.DisplayAlert("Error", "Failed to retrieve supplier ID", "Ok"); return; } var newSupplierId = supplierResponse.Id;
2. API路由错误:控制器名称冗余
你请求的API路由多了个Controller后缀:
string apiUrl = "https://localhost:7282/api/SupliersController/CreateSupplier";
ASP.NET Core路由默认会自动去掉控制器类名的Controller后缀,正确路由应该是:
string apiUrl = "https://localhost:7282/api/Supliers/CreateSupplier";
另外注意:代码里Supliers是拼写错误,应该是Suppliers?如果控制器类名是SuppliersController,路由要改成api/Suppliers/CreateSupplier,否则会直接404,返回空内容,进一步触发反序列化异常。
3. RelayCommand无法调试的可能原因
- 检查XAML里按钮的Command绑定是否正确,要绑定自动生成的
CreateSupplierCommand(RelayCommand会自动给方法加Command后缀) - 确认ViewModel已经正确设置为页面的BindingContext
- 检查
SupplierName和SelectedSections的绑定是否正常,如果绑定失败,可能会触发开头的判断提前返回,导致方法没执行 - 确保调试模式已启用,应用已正确附加调试器,在方法第一行手动加断点试试
4. 其他潜在问题
- 循环内重复提示跳转:你现在在
foreach循环里每创建一个SectionSupplier就弹提示、跳页面,应该把提示和跳转移到循环外面,不然选多个Section会重复触发 - API返回参数错误:SectionSupplier控制器的
CreatedAtAction调用缺少路由参数,正确写法要带上查询参数:
return CreatedAtAction(nameof(GetSectionSuplier), new { sectionId = sectionSuplier.SectionId, supplierId = sectionSuplier.SupplierId }, sectionSuplierResponse);
- 拼写不一致:代码里
SectionSuplier和SectionSupplier拼写混着用,建议统一命名避免低级错误
修复后的客户端代码示例
[RelayCommand] public async Task CreateSupplier() { try { if (string.IsNullOrWhiteSpace(SupplierName) || SelectedSections?.Count == 0) { await Shell.Current.DisplayAlert("Error", "No Field Should be empty", "Ok"); return; } var supplierDto = new SupplierDto() { SupplierName = SupplierName, ReturnClause = ReturnClause }; using (var client = new HttpClient()) { // 修正路由拼写与冗余后缀 string apiUrl = "https://localhost:7282/api/Suppliers/CreateSupplier"; client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // 用PostAsJsonAsync简化序列化,自动处理Content-Type var response = await client.PostAsJsonAsync(apiUrl, supplierDto); response.EnsureSuccessStatusCode(); // 主动检查HTTP状态码,直接抛出错误 var supplierResponse = await response.Content.ReadFromJsonAsync<SupplierDto>(); if (supplierResponse == null) { await Shell.Current.DisplayAlert("Error", "Failed to get supplier info", "Ok"); return; } var newSupplierId = supplierResponse.Id; foreach (var section in SelectedSections) { var sectionSupplierDto = new SectionSupplierDto { SupplierId = newSupplierId, SectionId = section.Id }; var sectionSupplierResponse = await client.PostAsJsonAsync( "https://localhost:7282/api/SectionSuppliers/CreateSectionSupplier", sectionSupplierDto); sectionSupplierResponse.EnsureSuccessStatusCode(); } // 移到循环外,只提示一次 await Shell.Current.DisplayAlert("Supplier added Successfully", $"The Supplier {SupplierName} was added successfully with the Id {newSupplierId}", "Ok"); await Shell.Current.GoToAsync($"///{nameof(SupplierPage)}"); } } catch (HttpRequestException ex) { await Shell.Current.DisplayAlert("API Error", ex.Message, "Ok"); } catch (Exception ex) { await Shell.Current.DisplayAlert("Error", ex.Message, "Ok"); } }
内容的提问来源于stack exchange,提问作者Yassine El mesbahy
相关产品推荐
相关产品推荐

