OData $ select失败,缺少属性错误

时间:2015-12-04 02:57:17

标签: api select odata serializer

我正在构建一个odata服务,用于从sql读取然后以json格式呈现结果。我虽然没有使用entityframework。

当应用$ select过滤器时,如果我的属性少于我的模型(删除可空的属性),我会收到以下错误。如果我有完全相同数量的属性,一切正常。

{
  "error": {
    "code": "",
    "message": "An error has occurred.",
    "innererror": {
      "message": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.",
      "type": "System.InvalidOperationException",
      "stacktrace": "",
      "internalexception": {
        "message": "The EDM instance of type '[PrototypeOData.Models.DefaultRule Nullable=True]' is missing the property 'DateLastModified'.",
        "type": "System.InvalidOperationException",
        "stacktrace": "   at System.Web.OData.EntityInstanceContext.GetPropertyValue(String propertyName)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralProperty(IEdmStructuralProperty structuralProperty, EntityInstanceContext entityInstanceContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralPropertyBag(IEnumerable`1 structuralProperties, EntityInstanceContext entityInstanceContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)\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.WriteObjectInline(Object graph, IEdmTypeReference expectedType, 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.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n   at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, 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.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n   at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__14.MoveNext()"
      }
    }
  }
}

我的模型看起来像这样:

public class DefaultRule
{
    public string Id { get; set; }
    public int? RequestedCount { get; set; }
    public DateTime? DateLastModified { get; set; }
}

在我的控制器中,呼叫如下:

        public IHttpActionResult Get(ODataQueryOptions<DefaultRule> options)
        {
            .............
            var res = options.SelectExpand.ApplyTo(result, new ODataQuerySettings() { PageSize = 100}).AsQueryable();
            //return result;
            return Ok(res, res.GetType());
        }

        private IHttpActionResult Ok(object content, Type type)
        {
            Type resultType = typeof(OkNegotiatedContentResult<>).MakeGenericType(type);
            return Activator.CreateInstance(resultType, content, this) as IHttpActionResult;
        }

有什么办法可以将特定属性标记为可选属性? 任何想法都表示赞赏。

1 个答案:

答案 0 :(得分:0)

这是因为$ select的结果不是您的原始模型。然后在序列化中发生错误。尝试在属性中添加pagesize,如:

[EnableQuery(PageSize=100)]

或创建自己的属性

public class MyEnableQueryAttribute : EnableQueryAttribute
{
    public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
    {
          return options.SelectExpand.ApplyTo(result, new ODataQuerySettings() { PageSize = 100}).AsQueryable().
    }
}

[MyEnableQueryAttribute]
public IHttpActionResult Get()
{
    ....
    return result;
}