在使用 WCF 数据服务客户端与我的 OData API 进行通信时,我偶尔需要使用 System.Data.Services.Client.DataServiceContext 的 AddRelatedObject 方法
这会生成一个POST
到端点,如下所示:
http://base_url/odata/Entity(key)/NavigationProperty
http请求的内容是序列化的NavigationProperty
实体。
由于该 URL 的帖子在默认的 odata 控制器中未映射,因此我编写了一个新的 EntitySetRoutingConvention 类:
Public Class AddRelatedObjectRoutingConvention
Inherits EntitySetRoutingConvention
Public Overrides Function SelectAction(odataPath As Http.OData.Routing.ODataPath, controllerContext As Http.Controllers.HttpControllerContext, actionMap As ILookup(Of String, Http.Controllers.HttpActionDescriptor)) As String
If controllerContext.Request.Method = Net.Http.HttpMethod.Post Then
If odataPath.PathTemplate = "~/entityset/key/navigation" Then
If actionMap.Contains("AddRelation") Then
Return "AddRelation"
End If
End If
End If
Return Nothing
End Function
End Class
我将此添加到默认路由约定列表并将其传递给MapODATARoute
例程。
在我的基本控制器中,我实现AddRelation
了,它被完美地调用了。
由此我能够得到odatapath
, 并对其进行解析以确定所需的类型和键。
我遇到的问题是,一旦我知道我的父实体是 aTenant
的键1
,并且实体中的NavigationProperty
ofUsers
是Tenant
一个User
实体,我无法弄清楚如何手动调用 anodatamediatypeformatter
将 http 内容反序列化为User
实体,以便我可以将其添加到Tenants
Users
集合中。
我已经查看了 OData 源,以了解 Web-API 管道如何调用和反序列化实体,但无法找到 OData 库获取 http 内容并将其转换为实体的点。
如果有人有想法为我指明正确的方向,如果我发现更多,我将继续研究和更新。
更新2013 年 6 月 28 日 多亏了 RaghuRam,我才得以离得更近。我看到的问题是 request.getconfiguration().formatters 或 odatamediatypeformatters.create 似乎都创建了特定于类型的反序列化器。
当我调用 ReadAsAsync 时,我收到错误消息:没有 MediaTypeFormatter 可用于从媒体类型为“application/atom+xml”的内容中读取“User”类型的对象。
如上面的帖子所示,控制器的上下文是租户,所以我相信格式化程序是为租户键入的,因此无法反序列化用户。
我尝试手动创建格式化程序,_childDefinition 是来自 odatapath 的导航属性的 EDM 类型参考。在这种情况下,用户。
Dim dser As New Formatter.Deserialization.ODataEntityDeserializer(_childDefinition, New Formatter.Deserialization.DefaultODataDeserializerProvider)
Dim ser As New Formatter.Serialization.ODataEntityTypeSerializer(_childDefinition, New Formatter.Serialization.DefaultODataSerializerProvider)
Dim dprovider As New Formatter.Deserialization.DefaultODataDeserializerProvider
dprovider.SetEdmTypeDeserializer(_childDefinition, dser)
Dim sprovider As New Formatter.Serialization.DefaultODataSerializerProvider
sprovider.SetEdmTypeSerializer(_childDefinition, ser)
Dim fmt As New Formatter.ODataMediaTypeFormatter(dprovider, sprovider, New List(Of Microsoft.Data.OData.ODataPayloadKind) From {Microsoft.Data.OData.ODataPayloadKind.Entry})
fmt.SupportedEncodings.Add(System.Text.Encoding.UTF8)
fmt.SupportedEncodings.Add(System.Text.Encoding.Unicode)
fmt.SupportedMediaTypes.Add(Headers.MediaTypeHeaderValue.Parse("application/atom+xml;type=entry"))
fmt.SupportedMediaTypes.Add(New Headers.MediaTypeHeaderValue("application/atom+xml"))
然后我尝试过:
request.content.ReadAsAsync(of User)(new List(of odatamediatypeformatter) from {fmt})
request.content.ReadAsAsync(of User)(request.getConfiguration().formatters)
request.content.ReadAsAsync(of User)(odatamediatypeformatters.create)
都给出了同样的错误,似乎我错过了一些明显的东西。
谢谢!
史蒂夫