Tom*_*mer 7 serialization json odata asp.net-web-api
我一直在尝试找到一个解决方案,用于自定义序列化过去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; }
}
Run Code Online (Sandbox Code Playgroud)
现在,假设客户端已将VirtualField1配置为"CompanyName".
我想要做的就是创建一个自定义JSON序列化器和反序列化器:
我已经阅读了谷歌可能找到的所有内容,但找不到任何有效的例子.以下是一些链接:
https :
//aspnetwebstack.codeplex.com/wikipage?title = DOMata20formatter%20extensibility**现在的OData API有点不同,但我认为原理是一样的.
从asp.net web api定制odata输出
在webapi中使用OData获取仅在运行时知道的属性
所有链接的常见(以及我发现的任何信息)是我必须从DefaultODataSerializerProvider继承并将其添加到我的格式化程序:
在WebApiConfig.cs上:
var customFormatters = ODataMediaTypeFormatters.Create(new CustomODataSerilizerProvider(), new CustomODataDeSerilizerProvider());
config.Formatters.InsertRange(0, customFormatters);
Run Code Online (Sandbox Code Playgroud)
和实际的提供者和序列化器:
public class CustomODataSerilizerProvider : DefaultODataSerializerProvider
{
public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
{
if (edmType.IsEntity())
{
return new CustomODataEntityTypeSerializer(edmType.AsEntity(), this);
}
return base.GetEdmTypeSerializer(edmType);
}
}
Run Code Online (Sandbox Code Playgroud)
**对于IQueryable结果,edmType.IsEntity()永远不会为true,因此它永远不会创建具体的序列化程序.如果我强制创建它仍然不会在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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我将具体的序列化程序更改为从ODataCollectionSerializer继承:
public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
{
if (edmType.IsCollection())
{
return new CollectionSerilizer(this);
}
return base.GetEdmTypeSerializer(edmType);
}
Run Code Online (Sandbox Code Playgroud)
和
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);
}
}
Run Code Online (Sandbox Code Playgroud)
它确实在WriteObject上的断点处停止但是不起作用并且基础正在抛出:"指定为集合的项类型的类型'Models.Customer'不是原始的或复杂的.ODataCollectionWriter只能编写原始值或复数值的集合. "
另一个有趣的事情是,即使我插入所谓的默认提供商:
var customFormatters = ODataMediaTypeFormatters.Create(new DefaultODataSerializerProvider(), new DefaultODataDeserializerProvider());
config.Formatters.InsertRange(0, customFormatters);
Run Code Online (Sandbox Code Playgroud)
无论他们的立场如何,也就是在开头:
config.Formatters.InsertRange(0, customFormatters);
Run Code Online (Sandbox Code Playgroud)
或者最后:
config.Formatters.AddRange(customFormatters);
Run Code Online (Sandbox Code Playgroud)
该OData的功能 -那就是-例如:$ exapnd在/的OData /客户$展开;图像完全消失,并在所有(这里是响应)不工作:
[{"Images":[],"CustomerId":1,"FirstName":"Bla","LastName":"Bla", "VirtualField1":null]
Run Code Online (Sandbox Code Playgroud)
尽管没有添加自定义格式化程序,但此实例中的图像未展开.
任何想法,想法,方向???
回答可能为时已晚,但我注意到,当涉及到OData V1-3和OData V4时微软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功能支持
支持函数调用的参数别名
在模型中支持camel case命名约定
支持$ filter中的cast()
支持开放复杂类型
删除了EntitySetController和AsyncEntitySetController
将$ link更改为$ ref
添加了属性路由支持
问问自己,你在使用OData是为了什么?我显然不能代表您的情况,但我会对您的用例进行分析: - 您正试图通过http向数据源发出复杂的问题,因为您不想要每当客户N想出一个新问题时改变界面. - 您正在尝试允许客户端请求他/她获取的数据的实际格式.CSV?XML?JSON?电子名片?哎呀,奥特?PDF?
如果这两个目标是你真正想要达到的目标,那就坚持使用V3.实现领域模型,你将为自己省去一大堆痛苦.
虽然我0.02美元.
| 归档时间: |
|
| 查看次数: |
5175 次 |
| 最近记录: |