我一直在努力寻找一种解决方案,用于自定义序列化过去2个月的OData控制器返回的实体!请帮忙!!!
用例非常简单,为了解决问题,我对其进行了简化。我有一些虚拟字段附加到我的模型中的某些实体,例如:
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序列化器和反序列化器:
我已经阅读了谷歌本可以找到的所有内容,但找不到任何有效的例子。
以下是一些链接:
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,如/ odata / Customers?$ expand =图像完全消失,根本不起作用(这是响应):< / p>
[{"Images":[],"CustomerId":1,"FirstName":"Bla","LastName":"Bla", "VirtualField1":null]
虽然没有添加自定义格式化程序,但此实例中的图片不已展开。
任何想法,想法,方向???
答案 0 :(得分:5)
回答可能为时已晚,但我注意到,当谈到OData V1-3和OData V4时,Microsoft的OData工具包之间的序列化方面的可用性存在显着差异。
我认为你正在使用V4,因为我也试图搞定DefaultODataSerializerProvider,并且没有成功。
然后我开始了一个新的Web Api项目,为OData V1-3添加了所有NuGet包,添加了一个Web Api OData控制器,并立即成功进行任何形式的序列化定制。
这是因为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实施的麻烦的情况下生活,而微软以一种比你更圣洁的方式遵循。 (可能是因为这是他们开始的东西)。
V4中最重要的功能: 支持OData模型中的别名属性
支持ODataConventionModelBuilder中的ComplexTypeAttribute,AssociationAttribute,TimesTampAttribute和ConcurrencyCheckAttribute
提供为行动提供友好标题的能力
与ODL UriParser集成
支持枚举,遏制和单身
支持原始类型的演员
添加了OData功能支持
支持函数调用的参数别名
支持模型
中的驼峰案例命名约定支持$ filter
中的cast()支持开放复杂类型
删除了EntitySetController和AsyncEntitySetController
将$ link更改为$ ref
添加了属性路由支持
问问自己,你在使用OData是为了什么? 我显然无法代表您的情况,但我会对您的用例进行分析: - 您试图允许通过http向数据源发出复杂问题,因为您不希望每次客户端N想出新问题时都更改界面。 - 您正在尝试允许客户端请求他/她获取的数据的实际格式。 CSV? XML? JSON?电子名片?哎呀,奥特? PDF?
如果这两个目标是你真正希望实现的目标,请坚持使用V3。实现领域模型,你将为自己省去一大堆痛苦。
我的0.02美元虽然。