You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
    }
}

问题分析

  1. 序列化/反序列化库不兼容:WebUI使用Newtonsoft.Json(JsonConvert)处理JSON,而ASP.NET Core ApiController默认使用System.Text.Json,两者默认的属性命名策略(如帕斯卡/驼峰)不同,导致部分属性无法正确绑定。
  2. DTO类型转换隐患:Get接口返回GetByIdProductDetailDto,但WebUI直接将其反序列化为UpdateProductDetailDto,若两个DTO属性定义不一致,会导致属性丢失。
  3. API参数绑定不明确:虽然ApiController默认从请求体绑定参数,但显式声明[FromBody]可避免潜在的绑定歧义。
  4. 请求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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:24:55