OData WebApi V4 .net - 自定义序列化

2024-01-20

我需要创建一个序列化器来支持以下所有任务:

  1. 删除空属性
  2. 删除空列表

我注意到的语法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)));

这应该结束了。 干杯。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OData WebApi V4 .net - 自定义序列化 的相关文章

随机推荐

  • 无法安装漂亮

    我无法 pip install Prettytable 安装它的最佳选择是什么 sudo pip vvv install prettytable Downloading unpacking prettytable Getting page
  • 通过 Intent 发送 Arraylist

    我怎样才能收到定制ArrayList从另一个活动通过Intent 例如 我有这个ArrayList在活动A中 ArrayList
  • 捕获生成器内的错误并随后继续

    我有一个应该运行几天的迭代器 我希望捕获并报告错误 然后我希望迭代器继续 或者整个过程可以重新开始 这是函数 def get units self scraper units scraper get units i 0 while True
  • 正则表达式接受命令并分割命令、参数和参数值

    下午好 我认为我在这项特殊任务中有点超出了我的能力范围 我正在尝试创建一个正则表达式匹配函数来输入命令 并拆分命令名称 参数和参数值 新变量 Name Something Force 结果应该是 新变量 Name 某物 Force 到目前为
  • 从字符串中删除隐藏字符

    我的问题 我有一个通过电子邮件发送新闻通讯的 NET 应用程序 在 Outlook 中查看新闻通讯时 Outlook 会显示一个问号来代替它无法识别的隐藏字符 这些隐藏字符来自最终用户 他们将组成时事通讯的 html 复制并粘贴到表单中并提
  • 表单识别器无效模型状态[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我们通过以下步骤尝试了表单识别器自定义训练 API 2 0 https pnagarjuna wordpress com 2020
  • android:将Tab的单击颜色设置为TableRow的背景颜色

    我有一个选项卡布局 我有一个带有动态添加行的表格布局 当选择 单击 TableRow 时 我想将其背景颜色设置为选项卡的按下或单击颜色 我不想设置任何静态颜色 但想使用默认主题颜色 如何获取 Tablayout 的颜色信息 How to h
  • Delphi中如何检查两个事件是否指向同一个过程?

    假设我有一个链接到 Button1Click 过程的 Button1 OnClick 事件 我还有 Button2 OnClick 链接到其他一些程序 如何检查这两个事件是否从运行时链接到不同或相同的过程 我尝试测试是否 Button1 O
  • 与串口“Verifone VX520”通信

    我正在通过串口将数据发送到 Verifone VX520 支付设备 这是我第一次尝试与此类设备进行通信 SerialObj Open 字符串输入 02hPUR 10 99 000000000004 634 4761739001010010F
  • XSL 用插入符替换空格

    更新的代码
  • 根据用户在 ASP.net 中的设置定期发送邮件?

    在我的网络应用程序中 我想根据用户自己预先选择的时间段为用户发送邮件 例如 每 3 天向用户 01 发送 1 封 HTML 邮件 每 20 天向用户 02 发送 1 封 HTML 邮件我怎样才能做到这一点 有资源吗 我可以通过我的应用程序从
  • com.hazelcast.nio.serialization.HazelcastSerializationException

    我正在运行一个 OSGI 插件项目 没有捆绑包 我在其中集成了 hazelcast 我 当我尝试将数据添加为字符串和测试 bean 的映射时 它被添加到淡褐色投射映射中 但是 二 当我尝试获取地图时 它显示错误如下 com hazelcas
  • Chrome扩展如何在扩展目录中写入文件

    这只是一个关于 chrome 扩展文件写入的简单问题 是否可以在chrome扩展目录中写入文件 我的意思是在我拥有清单文件和其他脚本的同一文件夹中写入一个文件 到目前为止 我发现我可以通过 XMLHttpRequest 读取目录中的文件 但
  • 关键点描述符 OpenCV

    我试图了解如何获取给定的描述符KeyPoint在 OpenCV 中 到目前为止 我的代码如下所示 include
  • Android Studio 和 Ryzen CPU?

    我知道它可能会被标记为重复 但没有一个线程对我有帮助 所以我决定自己做一个 I m a Java后端开发人员我决定学习一些 Android 的东西 几年前我在 Android Studio 工作过i5 4570处理器 然后我放弃了 现在我发
  • 使用 Entity Framework 和 Linq 进行动态排序

    我有另一个类似的问题在这里得到了回答 关于 NULL 值是订单的最后一个 在 Dynamic Linq Order By 上将 NULL 行保留在最后 https stackoverflow com questions 42277259 k
  • 我们如何使用 C# 将二进制数转换为八进制数?

    嘿 我正在开发一个应用程序 它将任何基数 如 2 8 10 16等 转换为用户所需的基数系统 我在将二进制数转换为八进制数时遇到问题 有人可以帮我吗 我尝试了一切 i am taking a binary number in value a
  • 在部署的应用程序上播放来自 s3 的文件时出现跨源资源策略问题

    我在 Heroku 上部署了一个应用程序 可以让我播放音频文件 你可以在这里查看https telecurve herokuapp com manage https telecurve herokuapp com manage 在我在 He
  • 使用 StoryBoards 时进行单元测试 cellForRowAtIndexPath

    如果我要从故事板中的标识符中取出单元格 如何以单元测试的方式调用 cellForRowAtIndexPath 并且不让单元格为零 UITableViewCell tableView UITableView tableView cellFor
  • OData WebApi V4 .net - 自定义序列化

    我需要创建一个序列化器来支持以下所有任务 删除空属性 删除空列表 我注意到的语法ODataMediaTypeFormatter已经变了 我在将序列化提供程序添加到管道时遇到问题 这是我尝试过的 在 WebApiConfig cs 上 var