如何向Asp.Net ODataFeed(V4)添加实例注释

时间:2014-08-06 22:32:03

标签: asp.net .net asp.net-web-api odata

我正在使用ODataLib 6.6.0和Microsoft.AspNet.OData 5.2.1 Nuget包。

我有以下代码,它创建了一个自定义序列化程序,用于向分页的OData Feed添加自定义注释。代码编译和调用正确,一直到添加自定义实例注释。

namespace WebApiTest.App_Start
{
    using Microsoft.OData.Core;
    using System.Collections.Generic;
    using System.Web.Http;
    using System.Web.OData.Formatter;
    using System.Web.OData.Formatter.Deserialization;
    using System.Web.OData.Formatter.Serialization;
    using WebApiTest.Controllers;

    public class FormatterConfiguration
    {
        public static void Register(HttpConfiguration config)
        {
            var formatters = ODataMediaTypeFormatters.Create(
                new CustomODataSerializerProvider(),
                new DefaultODataDeserializerProvider());
            config.Formatters.InsertRange(0, formatters);
        }
    }

    public class CustomODataSerializerProvider : DefaultODataSerializerProvider
    {
        private readonly CustomODataFeedSerializer _feedSerializer;

        public CustomODataSerializerProvider()
        {
            _feedSerializer = new CustomODataFeedSerializer(this);
        }

        public override ODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
        {
            var serializer = base.GetEdmTypeSerializer(edmType);
            var feedSerializer = serializer as ODataFeedSerializer;
            if (feedSerializer != null)
            {
                return _feedSerializer;
            }
            return serializer;
        }
    }

    public class CustomODataFeedSerializer : ODataFeedSerializer
    {
        public CustomODataFeedSerializer(ODataSerializerProvider serializerProvider)
            : base(serializerProvider)
        {
        }

        public override Microsoft.OData.Core.ODataFeed CreateODataFeed(System.Collections.IEnumerable feedInstance, Microsoft.OData.Edm.IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext)
        {
            ODataFeed feed = base.CreateODataFeed(feedInstance, feedType, writeContext);
            var result = feedInstance as IPageResultCustom;
            if (result != null)
            {
                var value = new ODataComplexValue();
                var properties = new List<ODataProperty>();
                properties.Add(new ODataProperty() { Name = "CustomProperty", Value = result.CustomProperty });
                value.Properties = properties;
                feed.InstanceAnnotations.Add(new ODataInstanceAnnotation("org.CustomComplexValue", value));
            }
            return feed;
        }
    }
}

我向请求中的包含HTTP标头Prefer: odata.include-annotations="*"Content-Type=application/json的Feed发出请求。然而,我在回复中没有注释。

跟踪OData框架代码时,在创建Func<string,bool> Microsoft.OData.Core.MessageWriterSettings.ShouldInludeAnnotations时永远不会设置内部属性ODataMessageWriters,因此ODataJsonLightValueSerializer.ShouldSkipAnnotation(string name)方法调用始终返回true。

这似乎是框架中的一个错误。我在配置或请求中遗漏了什么?

编辑2014年8月7日

该问题似乎与错误https://aspnetwebstack.codeplex.com/workitem/1880有关。

建议采用一种解决方法,即创建自定义ODataMediaTypeFormatter。但是,ODataMediaTypeFormatters.Create不是通用的,重新创建它涉及太多内部作用域的依赖项。这种解决方法至少是一项艰巨的任务。似乎ODataMediaTypeFormatter的可扩展性的实际限制仅限于实现自定义序列化器和/或反序列化器。

1 个答案:

答案 0 :(得分:1)

我可以通过覆盖DelegatingHandler.SendAsync来在响应头中设置Preference-Applied来解决这个问题:

return await base.SendAsync(request, cancellationToken).ContinueWith(t =>
{
   var response = t.Result;
   IEnumerable<string> headers;
   if (request.Headers.TryGetValues("Prefer", out headers))
   {
      response.Content.Headers.Add("Preference-Applied", headers);
   }
}