使用的软件:
考虑以下模型:
用户(UserId,姓名)
UserMessage(UserMessageId,User,Message,DateRead)
消息(MessageId,MessageType,Title,Text)
MessageType(MessageTypeId,Name)
用户有许多UserMessages,UserMessage连接用户和消息,并具有一些额外的属性。 Message具有MessageType属性,该属性也具有一些属性。
以下OData配置:
var builder = new ODataConventionModelBuilder();
builder.EntitySet<User>("Users");
// Configure an containment for messages.
builder.EntityType<User>().ContainsMany(u => u.Messages);
builder.EntityType<UserMessage>()
builder.EntitySet<Message>("Messages");
builder.EntitySet<MessageType>("MessageTypes");
var edmModel = builder.GetEdmModel();
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: edmModel);
说明:
在“UsersController”中,定义了以下方法来处理Messages:
的包含[EnableQuery]
public async Task<IQueryable<UserMessage>> GetMessages(int key)
使用包含选择所有用户消息时,一切都按预期工作:
/用户(1)/消息
返回:
{
"@odata.context":"https://host/$metadata#Users(1)/messages","value":[
{
"userId":1,"messageId":50,"dateRead":null,"userMessageId":481
}]
}
扩展消息也有效:
/用户(1)/消息?$扩大=消息
返回:
{
"@odata.context":"https://host/$metadata#Users(1)/messages","value":[
{
"userId":1,"messageId":50,"dateRead":null,"userMessageId":481,"message":{
"title":"Test","text":"Test","messageTypeId":1,"messageId":50
}
}
]
}
但是,在Message上扩展MessageType时,请求在客户端上的反序列化时失败(使用OData Client for .NET v6.11)。返回的JSON是:
{
"@odata.context":"https://host/$metadata#Users(1)/messages","value":[
{
"userId":1,"messageId":50,"dateRead":null,"userMessageId":481,"message":{
"title":"Test","text":"Test","messageTypeId":1,"messageId":50,"messageType":{
"@odata.type":"#Domain.Message.MessageType","name":"General","messageTypeId":1
}
}
}
]
}
客户端上的错误是:
编写JSON响应时,必须指定用户模型 实体集和实体类型必须传递给 ODataMessageWriter.CreateODataEntryWriter方法或 必须在ODataEntry或上设置ODataFeedAndEntrySerializationInfo 正在编写的ODataFeed。
堆栈跟踪:
[ODataException:在编写JSON响应时,必须指定用户模型,并且必须将实体集和实体类型传递给ODataMessageWriter.CreateODataEntryWriter方法,或者必须在正在写入的ODataEntry或ODataFeed上设置ODataFeedAndEntrySerializationInfo。 ] Microsoft.OData.Core.ODataFeedAndEntryTypeContext.ValidateAndReturn(T value)+74 Microsoft.OData.Core.Evaluation.ODataConventionalEntityMetadataBuilder.ComputeId()+71 Microsoft.OData.Core.Evaluation.ODataConventionalEntityMetadataBuilder.get_ComputedId()+136 Microsoft.OData.Client.Materialization.MaterializerEntry.UpdateEntityDescriptor()+426 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadEntryCore()+310 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.TryReadFeedOrEntry(Boolean lazy,ODataFeed&amp; feed,MaterializerEntry&amp; entry)+149 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadNavigationLink()+91 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadEntryCore()+256 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.TryReadFeedOrEntry(Boolean lazy,ODataFeed&amp; feed,MaterializerEntry&amp; entry)+149 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadNavigationLink()+91 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadEntryCore()+256 Microsoft.OData.Client.Materialization.d__0.MoveNext()+ 139 Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.Read()+68 Microsoft.OData.Client.Materialization.ODataEntityMaterializer.ReadImplementation()+113 Microsoft.OData.Client.MaterializeAtom.MoveNextInternal()+ 475 Microsoft.OData.Client.MaterializeAtom.MoveNext()+108 System.Linq.d__b1
1.MoveNext() +296 System.Linq.WhereSelectEnumerableIterator
2.MoveNext()+ 165 System.Collections.Generic.List1..ctor(IEnumerable
1个集合)+536 System.Linq.Enumerable.ToList(IEnumerable`1 source)+80
使用“odata.metadata = full”请求url的完整元数据信息时,服务器返回与客户端相同的错误:
HTTP/1.1 500 Internal Server Error
Content-Length: 3455
Content-Type: application/json; odata.metadata=full; charset=utf-8
Server: Microsoft-IIS/7.5
OData-Version: 4.0
X-Powered-By: ASP.NET
Date: Tue, 23 Jun 2015 09:47:20 GMT
{
"error":{
"code":"","message":"An error has occurred.","innererror":{
"message":"When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataEntryWriter method or the ODataFeedAndEntrySerializationInfo must be set on the ODataEntry or ODataFeed that is being written.","type":"Microsoft.OData.Core.ODataException","stacktrace":" at Microsoft.OData.Core.ODataFeedAndEntryTypeContext.ValidateAndReturn[T](T value)\r\n at Microsoft.OData.Core.Evaluation.ODataConventionalEntityMetadataBuilder.ComputeId()\r\n at Microsoft.OData.Core.Evaluation.ODataConventionalEntityMetadataBuilder.get_ComputedId()\r\n at Microsoft.OData.Core.Evaluation.ODataConventionalEntityMetadataBuilder.TryGetIdForSerialization(Uri& id)\r\n at Microsoft.OData.Core.JsonLight.ODataJsonLightEntryAndFeedSerializer.WriteEntryStartMetadataProperties(IODataJsonLightWriterEntryState entryState)\r\n at Microsoft.OData.Core.JsonLight.ODataJsonLightWriter.StartEntry(ODataEntry entry)\r\n at Microsoft.OData.Core.ODataWriterCore.InterceptException(Action action)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperty(KeyValuePair`2 navigationPropertyToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperties(IDictionary`2 navigationPropertiesToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperty(KeyValuePair`2 navigationPropertyToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperties(IDictionary`2 navigationPropertiesToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__13.MoveNext()"
}
}
}
我们需要在消息上展开messageType,因为我们需要客户端上的数据。
有什么建议吗?