gpt4 book ai didi

json - OData 序列化

转载 作者:行者123 更新时间:2023-12-04 12:21:23 25 4
gpt4 key购买 nike

在过去的 2 中,我一直试图找到一种解决方案来自定义序列化从 OData Controller 返回的实体。月 !请帮忙!!!

用例非常简单,为了解决问题,我进一步简化了它。我的模型中有一些附加到某些实体的虚拟字段,例如:

public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string VirtualField1 { get; set; }
public string VirtualField2 { get; set; }
public string VirtualField3 { get; set; }
}

现在,假设客户端已将 VirtualField1 配置为“CompanyName”。
我想要做的就是创建一个自定义的 JSON 序列化器和反序列化器:
  • 对客户的任何 GET 请求(当然还有 客户 - 即 - IQueryable<>)将通过这个序列化程序,在集合的情况下,它将用“公司名称”替换字段“VirtualField1”的名称为 每个顾客。
  • 任何 POST 请求都将进行相反的替换 - 即 - 用“VirtualField1”替换“CompanyName”。
    ** 实际的替换逻辑有点复杂,但思路是一样的。

  • 我已经阅读了谷歌可以找到的所有内容,但找不到任何工作示例。
    以下是一些链接:
    https://aspnetwebstack.codeplex.com/wikipage?title=OData%20formatter%20extensibility
    ** 当前的 OData API 现在有点不同,但我认为原理是相同的。
    customizing odata output from asp.net web api
    Using OData in webapi for properties known only at runtime

    所有链接(以及我为此找到的任何信息)的共同点是我必须从 DefaultODataSerializerProvider 继承并将其添加到我的格式化程序中:

    在 WebApiConfig.cs 上:
           var customFormatters = ODataMediaTypeFormatters.Create(new CustomODataSerilizerProvider(), new CustomODataDeSerilizerProvider());
    config.Formatters.InsertRange(0, customFormatters);

    以及实际的提供者和序列化程序:
     public class CustomODataSerilizerProvider : DefaultODataSerializerProvider
    {
    public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
    {
    if (edmType.IsEntity())
    {
    return new CustomODataEntityTypeSerializer(edmType.AsEntity(), this);
    }

    return base.GetEdmTypeSerializer(edmType);
    }
    }

    ** edmType.IsEntity() 对于 IQueryable 结果永远不是真的,所以它永远不会创建具体的序列化程序。如果我强制创建它仍然不会在 CreateEntity (或任何其他创建方法)上中断。
      public class CustomODataEntityTypeSerializer : ODataEntityTypeSerializer
    {
    public CustomODataEntityTypeSerializer(IEdmEntityTypeReference entityType, ODataSerializerProvider serializerProvider)
    : base(serializerProvider)
    {
    }

    public override ODataEntry CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
    {
    var oDataEntry = base.CreateEntry(selectExpandNode, entityInstanceContext);
    return oDataEntry;
    }
    }

    如果我将具体的序列化程序更改为从 ODataCollectionSerializer 继承:
      public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
    {

    if (edmType.IsCollection())
    {
    return new CollectionSerilizer(this);
    }

    return base.GetEdmTypeSerializer(edmType);
    }


    public class CollectionSerilizer : ODataCollectionSerializer
    {
    public CollectionSerilizer(ODataSerializerProvider serializerProvider) : base(serializerProvider)
    {
    }

    public override ODataCollectionValue CreateODataCollectionValue(IEnumerable enumerable, IEdmTypeReference elementType,
    ODataSerializerContext writeContext)
    {
    var oDataCollectionValue = base.CreateODataCollectionValue(enumerable, elementType, writeContext);
    return oDataCollectionValue;
    }

    public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
    {
    base.WriteObject(graph, type, messageWriter, writeContext);
    }
    }

    它确实在 WriteObject 上的断点处停止,但不起作用,并且基础正在抛出:
    “指定为集合项类型的‘Models.Customer’类型不是原始值或复杂值。ODataCollectionWriter 只能写入原始值或复杂值的集合。”

    另一个有趣的事情是,即使我插入了所谓的默认提供者:
    var customFormatters = ODataMediaTypeFormatters.Create(new DefaultODataSerializerProvider(), new DefaultODataDeserializerProvider());
    config.Formatters.InsertRange(0, customFormatters);

    无论他们的位置如何,要么是在开始时:
    config.Formatters.InsertRange(0, customFormatters);

    或最后:
    config.Formatters.AddRange(customFormatters);

    OData 功能 - 即 - 例如: $exapnd as in/odata/Customers?$expand=Images 完全消失并且根本不起作用(这是响应):
     [{"Images":[],"CustomerId":1,"FirstName":"Bla","LastName":"Bla", "VirtualField1":null]

    此实例中的图像为 不是 虽然没有添加他们所做的自定义格式化程序。

    任何想法,想法,方向???

    最佳答案

    现在回答可能为时已晚,但我注意到,当涉及到 OData V1-3 和 OData V4 时,Microsoft 的 OData 工具包之间的序列化在可用性方面存在显着差异。

    我认为您使用的是 V4,因为我也尝试过使用 DefaultODataSerializerProvider,但没有成功。

    然后我开始了一个新的 Web Api 项目,添加了 OData V1-3 的所有 NuGet 包,添加了一个 Web Api OData Controller ,并立即在任何形式的序列化定制中取得了成功。

    这是因为 OData V1-3 使用自定义 MediaTypeFormatters 的简单事实,就像 WebApi。之后就变得简单了。

    我不打算插入有关此的代码,因为使用 MediaTypeFormatter 的示例很多,如下所示:
    http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

    好吧,确实会丢失一些 V4 功能:
    http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22#OData

    但我相信您可以生活在没有严格的 V4 Oasis 实现的麻烦中,Microsoft 以一种比你更神圣的方式遵循。 (可能是因为这是他们的东西开始)。

    V4 中最重要的特性:
    支持 OData 模型中的别名属性

  • 谁在乎。

  • 支持 ODataConventionModelBuilder 中的 ComplexTypeAttribute、AssociationAttribute、TimesTampAttribute 和 ConcurrencyCheckAttribute
  • 你不需要它们。

  • 提供为 Action 提供友好标题的能力
  • 谁在乎。

  • 与 ODL UriParser 集成
  • 我不明白。

  • 支持枚举、包含和单例
  • 你不需要那个。

  • 支持基本类型转换
  • 你不需要那个。

  • 新增 OData 功能支持
  • 这是不幸的,但通过使用 OData 旁边的普通 ApiController 很容易解决。

  • 支持函数调用的参数别名
  • 你不需要那个,反正它很乱。

  • 支持模型中的驼峰命名约定
  • 很高兴它有支持,但我建议不要这样做。

  • 支持 $filter 中的 cast()
  • 不需要它。

  • 支持开放复杂类型
  • 是和?您有自定义序列化。您可以序列化您想要的任何类型。

  • 删除了 EntitySetController 和 AsyncEntitySetController
  • 甩掉包袱。

  • 将 $link 更改为 $ref
  • 好的。

  • 添加了属性路由支持
  • 不幸的是,您被您在 WebApiConfig 中定义的路由卡住了。大不了。

  • 问问自己,您使用 OData 做什么?
    我显然不能代表您的情况,但我将了解您的用例是什么:
    - 您试图允许通过 http 向数据源询问复杂的问题,因为您不想每次客户端 N 提出新问题时都更改界面。
    - 您试图让客户请求他/她返回的数据的实际格式是什么。 CSV? xml?杰森?电子名片?哎呀,odt? pdf?

    如果这两个目标是您真正想要实现的两个目标,请坚持使用 V3。您将免于实现域模型的一大堆痛苦。

    不过我的 0.02 美元。

    关于json - OData 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21404324/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com