ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – OData WebApi V4 .net – 自定义序列化

2019-07-10 14:18:23  阅读:181  来源: 互联网

标签:c net serialization asp-net odata


我需要创建一个Serializer来支持以下所有任务:

>删除空属性
>删除空列表

我注意到ODataMediaTypeFormatter的语法已被更改.

而我在将序列化提供程序添加到管道时遇到问题.

这是我尝试过的:

在WebApiConfig.cs上:

var odataFormatters = ODataMediaTypeFormatters.Create();
odataFormatters.Add(new MyDataMediaTypeFormatter());
config.Formatters.InsertRange(0, odataFormatters);

另外,我创建了以下Odatameditatypeformatter:

public class MyODataMediaTypeFormatter : ODataMediaTypeFormatter
{
    static IEnumerable<ODataPayloadKind> payloadKinds = new List<ODataPayloadKind>
    {

        ODataPayloadKind.Asynchronous,
        ODataPayloadKind.Batch,
        ODataPayloadKind.BinaryValue,
        ODataPayloadKind.Collection,
        ODataPayloadKind.EntityReferenceLink,
        ODataPayloadKind.EntityReferenceLinks,
        ODataPayloadKind.Error,
        ODataPayloadKind.Delta,
        ODataPayloadKind.IndividualProperty,
        ODataPayloadKind.MetadataDocument,
        ODataPayloadKind.Parameter,
        ODataPayloadKind.Resource,
        ODataPayloadKind.ServiceDocument,
        ODataPayloadKind.Unsupported,
        ODataPayloadKind.Value
    };

    public MyODataMediaTypeFormatter() : base(payloadKinds)
    {
    }
}

目前我检查了所有基本方法,并且在创建对我的OData控制器的Get / Post请求时,它们似乎都没有碰到断点.

任何人都设法在新版本的Microsoft.Aspnet.OData 7.0.1上做到了吗?

解决方法:

我找到了解决方案.
在新版本中,所有序列化和反序列化定制仅通过依赖注入启用.

首先,我们需要覆盖序列化提供程序:

/// <summary>
/// Provider that selects the IgnoreNullEntityPropertiesSerializer that omits null properties on resources from the response
/// </summary>
public class MySerializerProvider : DefaultODataSerializerProvider
{
    private readonly IgnoreNullsSerializer _propertiesSerializer;
    private readonly IgnoreEmptyListsResourceSetSerializer _ignoreEmptyListsSerializer;
    private readonly IgnoreEmptyListsCollectionSerializer _ignoreEmptyListsCollectionSerializer;

    /// <summary>
    /// constructor
    /// </summary>
    /// <param name="rootContainer"></param>
    public MySerializerProvider(IServiceProvider rootContainer)
        : base(rootContainer)
    {
        _ignoreEmptyListsSerializer = new IgnoreEmptyListsResourceSetSerializer(this);
        _propertiesSerializer = new IgnoreNullsSerializer(this);
        _ignoreEmptyListsCollectionSerializer = new IgnoreEmptyListsCollectionSerializer(this);
    }

    /// <summary>
    /// Mark edmtype to apply the serialization on
    /// </summary>
    /// <param name="edmType"></param>
    /// <returns></returns>
    public override ODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
    {
        // Support for Entity types AND Complex types
        if (edmType.Definition.TypeKind == EdmTypeKind.Entity || edmType.Definition.TypeKind == EdmTypeKind.Complex)
        {
            return _propertiesSerializer;
        }
        if (edmType.Definition.TypeKind == EdmTypeKind.Collection)
        {
            if(edmType.Definition.AsElementType().IsDecimal() || edmType.Definition.AsElementType().IsString())
                return _ignoreEmptyListsCollectionSerializer;

            return _ignoreEmptyListsSerializer;
        }            

        var result = base.GetEdmTypeSerializer(edmType);
        return result;
    }
}

您可能需要根据要覆盖其行为的EdmType覆盖不同的序列化程序.

我正在添加一个序列化程序示例,该序列化程序根据请求中的“HideEmptyLists”标题忽略实体中的空列表…

/// <inheritdoc />
/// <summary>
/// OData Entity Serializer that omits empty listss properties from the response
/// </summary>
public class IgnoreEmptyListsResourceSetSerializer : ODataResourceSetSerializer
{
    /// <summary>
    /// constructor
    /// </summary>
    /// <param name="provider"></param>
    public IgnoreEmptyListsResourceSetSerializer(ODataSerializerProvider provider) : base(provider) { }


    /// <inheritdoc />
    public override void WriteObjectInline(object graph, IEdmTypeReference expectedType, ODataWriter writer,
        ODataSerializerContext writeContext)
    {
        var shouldHideEmptyLists = writeContext.Request.GetHeader("HideEmptyLists");
        if (shouldHideEmptyLists != null)
        {     
            IEnumerable enumerable = graph as IEnumerable; // Data to serialize

            if (enumerable.IsNullOrEmpty())
            {
                return;
                //ignore
            }
        }

        base.WriteObjectInline(graph, expectedType, writer, writeContext);
    }

}

另一个忽略集合的空列表……

/// <inheritdoc />
/// <summary>
/// OData Entity Serilizer that omits null properties from the response
/// </summary>
public class IgnoreEmptyListsCollectionSerializer : ODataCollectionSerializer
{
    /// <summary>
    /// constructor
    /// </summary>
    /// <param name="provider"></param>
    public IgnoreEmptyListsCollectionSerializer(ODataSerializerProvider provider)
        : base(provider) { }


    /// <summary>
    /// Creates an <see cref="ODataCollectionValue"/> for the enumerable represented by <paramref name="enumerable"/>.
    /// </summary>
    /// <param name="enumerable">The value of the collection to be created.</param>
    /// <param name="elementType">The element EDM type of the collection.</param>
    /// <param name="writeContext">The serializer context to be used while creating the collection.</param>
    /// <returns>The created <see cref="ODataCollectionValue"/>.</returns>
    public override ODataCollectionValue CreateODataCollectionValue(IEnumerable enumerable, IEdmTypeReference elementType,
        ODataSerializerContext writeContext)
    {

        var shouldHideEmptyLists = writeContext.Request.GetHeader("HideEmptyLists");
        if (shouldHideEmptyLists != null)
        {
            if (enumerable.IsNullOrEmpty())
            {
                return null;
                //ignore
            }
        }

        var result = base.CreateODataCollectionValue(enumerable, elementType, writeContext);            
        return result;
    }
}

最后,我将展示如何将序列化提供程序注入我们的OData管道:

        config.MapODataServiceRoute(odata, odata, builder => builder
            .AddService<ODataSerializerProvider>(ServiceLifetime.Scoped, sp => new MySerializerProvider(sp)));

这应该包装起来.
干杯.

标签:c,net,serialization,asp-net,odata
来源: https://codeday.me/bug/20190710/1424741.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有