JSON.NET作为的WebAPI 2的OData串行VS ODataMediaTypeFormatter [英] JSON.NET as a WebAPI 2 OData serializer vs ODataMediaTypeFormatter

查看:511
本文介绍了JSON.NET作为的WebAPI 2的OData串行VS ODataMediaTypeFormatter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用JSON.NET中的WebAPI 2堆栈默认序列。我实现了JsonMediaTypeFormatter,在我使用JSON.NET串行的序列化/反序列化数据,并创建JsonContentNegotiator使用此媒体类型格式。所有作品除了OData的查询精 - 如果我添加[可查询]元数据OT操作方法,那么响应对象不包含任何元数据信息,只有实体的名单。

I'm trying to use JSON.NET as a default serializer in WebAPI 2 stack. I've implemented JsonMediaTypeFormatter, in which I've used JSON.NET serializer for serialize/deserialize data and created JsonContentNegotiator for using this media type formatter. All works fine except OData querying - if I add [Queryable] metadata ot action method, then response object doesn't contains any metadata information, only list of entities.

小例子。我的操作方法:

Small example. My action method:

[Queryable]
public async Task<PageResult<RuleType>> GetRuleType(ODataQueryOptions<RuleType> options)
{
    var ret = await _service.ListRuleTypesAsync(options);
    return new PageResult<RuleType>(
        ret,
        Request.GetNextPageLink(),
        Request.GetInlineCount());
}

如果我使用默认的OData序列化,并呼吁通过规则类型的一些查询(例如 - ... / ODATA / RuleType $ inlinecount =所有页和放大器; $跳过= 0&放大器; $顶部= 1 ),我收到的元数据信息经典的OData响应和count属性:

If I use default OData serialize and call some query by Rule type (for example - .../odata/RuleType?$inlinecount=allpages&$skip=0&$top=1), I receive classic OData response with metadata info and count property:

odata.metadata ".../odata/$metadata#RuleType" 
odata.count    "2" 
value
        0    {
                 Id: 1
             Name: "General"
             Code: "General"
             Notes: null
             }

(某些字段跳过,但我有一个空值Notes属性)
但是,如果我我的 JsonContentNegotiator JsonMediaTypeFormatter 添加为串行 - 我只接受实体的名单:

(some fields skipped, but I have Notes property with null value) But if I add my JsonContentNegotiator with JsonMediaTypeFormatter as a serializer - I receive only list of entities:

[
  {
    "Id": 1,
    "Name": "General",
    "Code": "General"
  }
]

(没有注释字段,因为这里的 NullValueHandling.Ignore
更。如果我删除的操作方法 [可查询] 属性 - 我收到另一个结果是:

(no Notes field here because of NullValueHandling.Ignore) Even more. If I remove [Queryable] attribute in action method - I receive another result:

{
  "Items": [
    {
      "Id": 1,
      "Name": "General",
      "Code": "General"
    }
  ],
  "Count": 2
}

在这种情况下,我在这里收到的计数,但仍然没有元数据。也ODATA响应属性名称完全不同于默认值。

In this case I've received Count, but still no metadata here. And also odata response property names completely differs from default.

我的脑子里吹了起来。我只是想在我的web应用程序的任何部分使用JSON.NET作为我的串行(因为一些有实力的限制)。我怎样才能做到这一点?

My mind is blowing up. I just want to use JSON.NET as my serializer in any part of my web app (because of some strong restrictions). How can I do this?

推荐答案

我已经想通了,我的问题,并找到了解决办法。 OData的使用单独的媒体类型格式化,从ODataMediaTypeFormatter继承。还使用OData的序列化和反序列化不同的格式化。对于更换这种行为,我们必须实现ODataDeserializerProvider和/或ODataSerializerProvider类的后裔和

I've already figured out my problem and found the solution. OData uses separate media type formatters, inherited from ODataMediaTypeFormatter. Also OData uses different formatters for serialization and deserialization. For replacing this behavior we have to implement descendants of ODataDeserializerProvider and/or ODataSerializerProvider classes and add those classes to the HttpConfiguration.Formatters collections by

var odataFormatters = ODataMediaTypeFormatters
    .Create(new MyODataSerializerProvider(), new MuODataDeserializerProvider());
config.Formatters.AddRange(odataFormatters);

小反序列化提供商例如:

Small deserialization provider example:

public class JsonODataDeserializerProvider : ODataDeserializerProvider
{
    public override ODataEdmTypeDeserializer GetEdmTypeDeserializer(IEdmTypeReference edmType)
    {
        var kind = GetODataPayloadKind(edmType);

        return new JsonODataEdmTypeDeserializer(kind, this);
    }

    private static ODataPayloadKind GetODataPayloadKind(IEdmTypeReference edmType)
    {
        switch (edmType.TypeKind())
        {
            case EdmTypeKind.Entity:
                return ODataPayloadKind.Entry;
            case EdmTypeKind.Primitive:
            case EdmTypeKind.Complex:
                return ODataPayloadKind.Property;
            case EdmTypeKind.Collection:
                IEdmCollectionTypeReference collectionType = edmType.AsCollection();
                return collectionType.ElementType().IsEntity() ? ODataPayloadKind.Feed : ODataPayloadKind.Collection;
            default:
                return ODataPayloadKind.Entry;
        }
    }

    public override ODataDeserializer GetODataDeserializer(IEdmModel model, Type type, HttpRequestMessage request)
    {
        var edmType = model.GetEdmTypeReference(type);

        return edmType == null ? null : GetEdmTypeDeserializer(edmType);
    }
}

ODataDeserializer:

ODataDeserializer:

public class JsonODataEdmTypeDeserializer : ODataEdmTypeDeserializer
{
    public JsonODataEdmTypeDeserializer(ODataPayloadKind payloadKind) : base(payloadKind)
    {
    }

    public JsonODataEdmTypeDeserializer(ODataPayloadKind payloadKind, ODataDeserializerProvider deserializerProvider) : base(payloadKind, deserializerProvider)
    {
    }

    public override object Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
    {
        var data = readContext.Request.Content.ReadAsStringAsync().Result;

        return JsonConvert.DeserializeObject(data, type);
    }
}

和我来自的WebAPI的OData源$ C ​​$ C也开始加入EdmLibsHelper类在我和GetEdmTypeReference()和GetEdmType()方法的项目,因为这个类是内部的。

And I also have added EdmLibsHelper class from WebAPI OData source code in my project with GetEdmTypeReference() and GetEdmType() methods because this class is internal.

这篇关于JSON.NET作为的WebAPI 2的OData串行VS ODataMediaTypeFormatter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆