我正在将JSON从客户端补丁到我的Web API 2控制器。
请求如下:
Request URL: http://localhost:28029/PlaylistItem/5df2b99f-e021-4c81-8ff5-a34c013470aa
Request Payload: { sequence: 5000 }
我的控制器的方法看起来像:
[Route("{id:guid}")]
[HttpPatch]
public void Patch(Guid id, Delta<PlaylistItemDto> playlistItemDto)
{
}
playlisttitemdto的样子:
public class PlaylistItemDto
{
public Guid PlaylistId { get; set; }
public Guid Id { get; set; }
public int Sequence { get; set; }
...
}
这将成功地向控制器发送请求,但由于区分大小写而无法正常工作。OData库不能正确地将sequence转换为sequence。
我发现一个线程关于这个问题,asp.net mvc web api部分更新与OData补丁,但我发现解决方案是平淡无奇的。这个问题目前没有有效的解决方案吗?区分大小写似乎是将JSON数据从客户机补丁到服务器的一个非常常见的用例。
使用继承CamelCasePropertyNamesContractResolver的自定义契约解析器和实现CreateContract方法来查看delta的具体类型并获得实际的属性名称,而不是使用来自json的名称,这可以很容易地完成。摘要如下:
public class DeltaContractResolver : CamelCasePropertyNamesContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
// This class special cases the JsonContract for just the Delta<T> class. All other types should function
// as usual.
if (objectType.IsGenericType &&
objectType.GetGenericTypeDefinition() == typeof(Delta<>) &&
objectType.GetGenericArguments().Length == 1)
{
var contract = CreateDynamicContract(objectType);
contract.Properties.Clear();
var underlyingContract = CreateObjectContract(objectType.GetGenericArguments()[0]);
var underlyingProperties =
underlyingContract.CreatedType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in underlyingContract.Properties)
{
property.DeclaringType = objectType;
property.ValueProvider = new DynamicObjectValueProvider()
{
PropertyName = this.ResolveName(underlyingProperties, property.PropertyName),
};
contract.Properties.Add(property);
}
return contract;
}
return base.CreateContract(objectType);
}
private string ResolveName(PropertyInfo[] properties, string propertyName)
{
var prop = properties.SingleOrDefault(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));
if (prop != null)
{
return prop.Name;
}
return propertyName;
}
}