Web API 2中如何为Created ActionResult定义序列化以截断属性
解决Web API 2中Created响应截断指定属性的问题
你已经找对方向啦——自定义CamelCasePropertyNamesContractResolver就是Web API里控制Json序列化规则的核心方式,咱们把你没写完的代码补全,再配上配置步骤就能实现需求:
1. 完善自定义ContractResolver与截断逻辑
首先要实现一个自定义的ContractResolver,并搭配IValueProvider来处理ItemDescriptions属性的截断:
public class ItemContractResolver : CamelCasePropertyNamesContractResolver { // 可根据需求调整最大截断长度 private readonly int _maxDescriptionLength = 100; protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); // 定位到ItemDescriptions属性 if (member.Name == nameof(Item.ItemDescriptions) && property.PropertyType == typeof(string)) { // 替换属性的ValueProvider,用我们的截断逻辑 property.ValueProvider = new TruncatedStringValueProvider(member, _maxDescriptionLength); } return property; } } // 自定义ValueProvider,负责具体的字符串截断 public class TruncatedStringValueProvider : IValueProvider { private readonly MemberInfo _member; private readonly int _maxLength; public TruncatedStringValueProvider(MemberInfo member, int maxLength) { _member = member; _maxLength = maxLength; } public object GetValue(object target) { // 获取原始属性值 var originalValue = (_member as PropertyInfo)?.GetValue(target) as string; if (string.IsNullOrEmpty(originalValue)) return originalValue; // 执行截断:超过长度则截断并添加省略号 return originalValue.Length > _maxLength ? originalValue.Substring(0, _maxLength) + "..." : originalValue; } public void SetValue(object target, object value) { // 反序列化场景如果不需要处理,直接赋值即可;有特殊需求可以在这里扩展 (_member as PropertyInfo)?.SetValue(target, value); } }
2. 配置Web API使用自定义规则
全局生效(所有Json响应都截断该属性)
在WebApiConfig.cs里替换默认的序列化规则:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 其他路由、过滤器配置... // 绑定自定义ContractResolver到Json格式化器 config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new ItemContractResolver(); } }
仅在Created响应中生效(不影响其他接口)
如果不想全局修改,只想在返回Created响应时应用截断,可以手动构造HttpResponseMessage来指定序列化规则:
public async Task<IHttpActionResult> PostItem(Item item) { // 业务逻辑:保存item到数据库、生成Id等... // 单独配置当前响应的序列化规则 var serializerSettings = new JsonSerializerSettings { ContractResolver = new ItemContractResolver(), Formatting = Formatting.Indented }; // 手动序列化item var serializedItem = JsonConvert.SerializeObject(item, serializerSettings); var content = new StringContent(serializedItem, Encoding.UTF8, "application/json"); // 构造Created响应,设置Location头 var response = Request.CreateResponse(HttpStatusCode.Created, content); response.Headers.Location = new Uri(Request.RequestUri + "/" + item.Id); return ResponseMessage(response); }
额外说明
- 如果需要更灵活的截断逻辑(比如按单词边界截断、忽略HTML标签等),只需要修改
TruncatedStringValueProvider.GetValue里的代码即可。 - 如果你之前的代码卡在
CreateProperty方法,核心就是通过替换ValueProvider来介入属性的序列化过程,这是Json.NET里自定义属性序列化的标准方式。
内容的提问来源于stack exchange,提问作者qubits
相关产品推荐
相关产品推荐

