多个扩展级别无效的OData包含

时间:2015-06-23 09:59:54

标签: .net odata asp.net-web-api2

使用的软件:

  • ASP.NET Web API 2.2
  • OData v4.0
  • 用于.NET的OData客户端(v 6.11)

考虑以下模型:

  

用户(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);

说明:

  1. 需要将Message和MessageType配置为实体集,因为我们需要能够使用相应的控制器添加单个消息和消息类型。
  2. UserMessages不作为实体集公开,而是作为实体集“Users”的包含公开。
  3. 在“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.List 1..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,因为我们需要客户端上的数据。

    有什么建议吗?

0 个答案:

没有答案