POST请求遇400错误,MVC微服务更新产品详情时属性为空
MVC应用更新产品详情时微服务接收数据部分为空的问题
我搭建了具备CRUD功能的MVC应用用于数据更新,WebUI的更新控制器会向微服务的API控制器发起HTTP请求,但微服务控制器接收的数据存在部分属性为空的情况。具体表现为:点击产品按钮可正常跳转并获取产品数据,但执行更新操作失败;而使用Postman调用微服务的更新接口却能成功。相关代码如下:
// 产品详情服务 public class ProductDetailService : IProductDetailService { public async Task<GetByIdProductDetailDto> GetByProductIdProductDetailAsync(string id) { var values = await _productDetailCollection.Find<ProductDetail>(x => x.ProductID == id).FirstOrDefaultAsync(); return _mapper.Map<GetByIdProductDetailDto>(values); } public async Task UpdateProductDetailAsync(UpdateProductDetailDto updateProductDetailDto) { var values = _mapper.Map<ProductDetail>(updateProductDetailDto); await _productDetailCollection.FindOneAndReplaceAsync(x => x.ProductDetailID == updateProductDetailDto.ProductDetailID, values); } }
// 微服务产品详情API控制器 [AllowAnonymous] [Route("api/[controller]")] [ApiController] public class ProductDetailsController : ControllerBase { [HttpGet("GetProductDetailByProductId")] public async Task<IActionResult> GetProductDetailByProductId(string id) { var values = await _productDetailService.GetByProductIdProductDetailAsync(id); return Ok(values); } [HttpPut] public async Task<IActionResult> updateProductDetail(UpdateProductDetailDto updateProductDetailDto) { await _productDetailService.UpdateProductDetailAsync(updateProductDetailDto); return Ok("Ürün Detayı Başarılıyla Güncellendi"); // 土耳其语:产品详情更新成功 } }
// WebUI产品详情控制器 [Area("Admin")] [AllowAnonymous] [Route("Admin/ProductDetail")] public class ProductDetailController : Controller { [Route("UpdateProductDetail/{id}")] [HttpGet] public async Task<IActionResult> UpdateProductDetail(string id) { var client = _httpClientFactory.CreateClient(); var responseMessage = await client.GetAsync("https://localhost:7070/api/ProductDetails/GetProductDetailByProductId?id=" + id); if (responseMessage.IsSuccessStatusCode) { var jsonData = await responseMessage.Content.ReadAsStringAsync(); var values = JsonConvert.DeserializeObject<UpdateProductDetailDto>(jsonData); return View(values); } return View(); } [Route("UpdateProductDetail/{id}")] [HttpPost] public async Task<IActionResult> UpdateProductDetail(UpdateProductDetailDto updateProductDetailDto) { var client = _httpClientFactory.CreateClient(); var jsonData = JsonConvert.SerializeObject(updateProductDetailDto); StringContent stringContent = new StringContent(jsonData, Encoding.UTF8, "application/json"); var responseMessage = await client.PutAsync("https://localhost:7070/api/ProductDetails/", stringContent); if (responseMessage.IsSuccessStatusCode) { return RedirectToAction("ProductListWithCategory", "Product", new { area = "Admin" }); } return View(); } }
问题分析
- 序列化/反序列化库不兼容:WebUI使用Newtonsoft.Json(
JsonConvert)处理JSON,而ASP.NET Core ApiController默认使用System.Text.Json,两者默认的属性命名策略(如帕斯卡/驼峰)不同,导致部分属性无法正确绑定。 - DTO类型转换隐患:Get接口返回
GetByIdProductDetailDto,但WebUI直接将其反序列化为UpdateProductDetailDto,若两个DTO属性定义不一致,会导致属性丢失。 - API参数绑定不明确:虽然
ApiController默认从请求体绑定参数,但显式声明[FromBody]可避免潜在的绑定歧义。 - 请求URL格式问题:WebUI的Put请求URL末尾多了斜杠,可能引发路由匹配异常。
解决方案
1. 统一序列化配置
在微服务项目中切换为Newtonsoft.Json,与WebUI保持一致:
- 安装NuGet包:
Microsoft.AspNetCore.Mvc.NewtonsoftJson - 在
Program.cs中添加配置:builder.Services.AddControllers() .AddNewtonsoftJson(options => { // 保持与WebUI一致的帕斯卡命名策略 options.SerializerSettings.ContractResolver = new DefaultContractResolver(); });
2. 检查并统一DTO定义
确保GetByIdProductDetailDto和UpdateProductDetailDto的属性完全匹配(名称、类型、可空性),或直接复用同一DTO类完成获取和更新操作,避免转换丢失数据。
3. 显式添加[FromBody]特性
修改微服务的Put接口参数,明确指定从请求体读取数据:
[HttpPut] public async Task<IActionResult> updateProductDetail([FromBody] UpdateProductDetailDto updateProductDetailDto) { await _productDetailService.UpdateProductDetailAsync(updateProductDetailDto); return Ok("产品详情更新成功"); }
4. 修正请求URL
移除WebUI中Put请求URL末尾的斜杠:
var responseMessage = await client.PutAsync("https://localhost:7070/api/ProductDetails", stringContent);
5. 调试序列化结果
在WebUI的Post方法中输出序列化后的JSON,验证所有属性是否正确序列化:
var jsonData = JsonConvert.SerializeObject(updateProductDetailDto); Console.WriteLine(jsonData); // 查看控制台输出的JSON内容
内容的提问来源于stack exchange,提问作者Onur
相关产品推荐
相关产品推荐

