使用OData的Web API 2补丁-如何最好地处理大小写敏感性



我正在将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;
        }
}

最新更新