在ASP.NET对接Shopify的PUT请求中忽略Variant类的Quantity属性
解决ASP.NET中Variant类在PUT请求忽略Quantity属性的问题
针对你遇到的POST允许传入Quantity、PUT请求需忽略该属性的需求,这里提供几种实用方案:
方案1:创建专用DTO(推荐)
最清晰且易维护的方式是为POST和PUT请求分别定义数据传输对象(DTO),明确区分不同请求允许的字段:
// 用于POST请求的DTO,包含Quantity属性 public class PostVariantDto { public long Id { get; set; } public string Title { get; set; } public decimal Weight { get; set; } public decimal Price { get; set; } public int Quantity { get; set; } } // 用于PUT请求的DTO,排除Quantity属性 public class PutVariantDto { public long Id { get; set; } public string Title { get; set; } public decimal Weight { get; set; } public decimal Price { get; set; } }
在控制器中分别接收对应DTO,再通过AutoMapper等工具映射到你的Variant实体类:
[HttpPost] public IActionResult CreateVariant([FromBody] PostVariantDto postDto) { var variant = _mapper.Map<Variant>(postDto); // 执行创建逻辑 return Ok(variant); } [HttpPut("{id}")] public IActionResult UpdateVariant(long id, [FromBody] PutVariantDto putDto) { var existingVariant = _variantRepository.GetById(id); _mapper.Map(putDto, existingVariant); // 执行更新逻辑 return Ok(existingVariant); }
这种方式完全隔离了不同请求的字段要求,避免了单一类的多场景适配问题,后续维护也更直观。
方案2:在PUT控制器方法中忽略属性绑定
如果不想额外创建DTO,可以在PUT请求的控制器方法中手动移除Quantity的绑定值,确保该字段不会被更新:
[HttpPut("{id}")] public IActionResult UpdateVariant(long id, [FromBody] Variant variant) { // 从ModelState中移除Quantity属性,忽略客户端传入的值 ModelState.Remove(nameof(Variant.Quantity)); if (!ModelState.IsValid) { return BadRequest(ModelState); } // 获取数据库中已存在的Variant实例,保留原有Quantity值 var existingVariant = _variantRepository.GetById(id); existingVariant.Title = variant.Title; existingVariant.Weight = variant.Weight; existingVariant.Price = variant.Price; // 执行更新逻辑 _variantRepository.Update(existingVariant); return Ok(existingVariant); }
注意:这种方式仅处理服务器接收时的忽略,如果需要在PUT响应中也隐藏Quantity属性,还需额外配置序列化规则。
方案3:条件序列化(针对输出/输入控制)
如果需要在序列化(响应输出)或反序列化(请求输入)时根据请求方法动态忽略Quantity,可以自定义JSON转换器:
示例(System.Text.Json):
public class VariantConditionalConverter : JsonConverter<Variant> { private readonly bool _ignoreQuantity; // 通过构造函数传入是否忽略Quantity的标记 public VariantConditionalConverter(bool ignoreQuantity) { _ignoreQuantity = ignoreQuantity; } public override Variant Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; var variant = new Variant { Id = root.GetProperty("Id").GetInt64(), Title = root.GetProperty("Title").GetString(), Weight = root.GetProperty("Weight").GetDecimal(), Price = root.GetProperty("Price").GetDecimal() }; // 仅在不忽略时读取Quantity if (!_ignoreQuantity && root.TryGetProperty("Quantity", out var quantityProp)) { variant.Quantity = quantityProp.GetInt32(); } return variant; } public override void Write(Utf8JsonWriter writer, Variant value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteNumber("Id", value.Id); writer.WriteString("Title", value.Title); writer.WriteNumber("Weight", value.Weight); writer.WriteNumber("Price", value.Price); // 仅在不忽略时写入Quantity if (!_ignoreQuantity) { writer.WriteNumber("Quantity", value.Quantity); } writer.WriteEndObject(); } }
然后在控制器中根据请求方法配置转换器:
[HttpPut("{id}")] public IActionResult UpdateVariant(long id, [FromBody] Variant variant) { // 处理更新逻辑... var options = new JsonSerializerOptions(); options.Converters.Add(new VariantConditionalConverter(ignoreQuantity: true)); return Json(updatedVariant, options); } [HttpPost] public IActionResult CreateVariant([FromBody] Variant variant) { // 处理创建逻辑... var options = new JsonSerializerOptions(); options.Converters.Add(new VariantConditionalConverter(ignoreQuantity: false)); return Json(createdVariant, options); }
这种方式灵活性高,但代码复杂度也相对较高,适合无法使用DTO的场景。
内容的提问来源于stack exchange,提问作者Saghar Francis
相关产品推荐
相关产品推荐

