Asp.net web api 如何在web api OData查询中启用$select
如何使web api能够提供可通过$select OData操作符查询的数据 我使用的是Web API 2.2(或Microsort.AspNet.WebApi 5.2.2),我没有使用EF,我的后端是异步的,不支持IQueryable。在传递给客户机之前,我不介意查询整个数据集并在web服务器上进行过滤 我下面的内容并不理想,因为它返回一个Asp.net web api 如何在web api OData查询中启用$select,asp.net-web-api,odata,Asp.net Web Api,Odata,如何使web api能够提供可通过$select OData操作符查询的数据 我使用的是Web API 2.2(或Microsort.AspNet.WebApi 5.2.2),我没有使用EF,我的后端是异步的,不支持IQueryable。在传递给客户机之前,我不介意查询整个数据集并在web服务器上进行过滤 我下面的内容并不理想,因为它返回一个任务,但我不知道如何用另一种方式来做,事实上我根本不知道如何做 下面的代码可以工作,但是在使用$select时会抛出一个错误(我们称之为代码块A): 问题与
任务
,但我不知道如何用另一种方式来做,事实上我根本不知道如何做
下面的代码可以工作,但是在使用$select时会抛出一个错误(我们称之为代码块A):
问题与任务无关 经过一些研究,问题在于A区的这行代码:
queryOptions.ApplyTo(result.AsQueryable()) as IQueryable<Cars>
在方法返回后,asp.net odata实现会自动应用过滤器
如果您希望在代码中应用查询选项,然后返回IQueryable以外的内容,则applyTo非常有用
关于块B中的序列化错误(在添加了application/json之后),我不知道 问题与任务无关 经过一些研究,问题在于A区的这行代码:
queryOptions.ApplyTo(result.AsQueryable()) as IQueryable<Cars>
在方法返回后,asp.net odata实现会自动应用过滤器
如果您希望在代码中应用查询选项,然后返回IQueryable以外的内容,则applyTo非常有用
关于块B中的序列化错误(在添加了application/json之后),我不知道 我发现了这种方法:
[启用查询]
公共异步任务GetCars()
{
//从上下文返回IQueryable,不执行对数据库的请求
返回wait Task.FromResult(_context.GetCarsQuery());
}
我发现了这种方法:
[启用查询]
公共异步任务GetCars()
{
//从上下文返回IQueryable,不执行对数据库的请求
返回wait Task.FromResult(_context.GetCarsQuery());
}
代码块A的错误是什么?对于代码块B(http 406),请快速查看@MarvinSmit,请参阅上面的更新问题和信息。感谢406上的信息,我在其中添加了application/json,它现在看起来像是一个序列化错误,类似于上面代码块a的错误。有趣的是,返回IQueryable时不会发生这种情况-只有在将其包装到任务中时才会发生。然而,由于我的后端是异步的,我有什么选择呢?解决方案可能是在IQueryable实现(la')的下面封装一个异步提供程序。工作太多了!虽然我不确定为什么在您的案例中,这是使用webapi的OData的“典型错误”。(尝试在任何OData端点上执行此操作;使用属性的$select并确保请求XML作为输出)。它只是不喜欢序列化“弱类型”对象。因此,JSON。但您正在请求JSON。()嘿@MarvinSmit,请看下面的@Fabians回答。它起作用了。但是,我将尝试指定application/json,并使用query.ApplyTo
方法返回async Task
。通过async Task
执行此操作并不容易,尽管使用自定义格式化程序可能:代码块A的错误是什么?对于代码块B(http 406),请快速查看@MarvinSmit,请参阅上面的更新问题和信息。感谢406上的信息,我在其中添加了application/json,它现在看起来像是一个序列化错误,类似于上面代码块a的错误。有趣的是,返回IQueryable时不会发生这种情况-只有在将其包装到任务中时才会发生。然而,由于我的后端是异步的,我有什么选择呢?解决方案可能是在IQueryable实现(la')的下面封装一个异步提供程序。工作太多了!虽然我不确定为什么在您的案例中,这是使用webapi的OData的“典型错误”。(尝试在任何OData端点上执行此操作;使用属性的$select并确保请求XML作为输出)。它只是不喜欢序列化“弱类型”对象。因此,JSON。但您正在请求JSON。()嘿@MarvinSmit,请看下面的@Fabians回答。它起作用了。不过,我将尝试指定application/json,并使用query.ApplyTo
方法返回async Task
。通过async Task
执行此操作并不容易,尽管使用自定义格式化程序可能会这样做:只需删除一些多余的代码行即可。谢谢@Fabian。我开始尝试返回异步任务
,但由于某种原因,它没有序列化。仔细想想,这可能是因为Accept头。哦,你的解决方案是显而易见的,而且是成功的。只需删除一些多余的代码行即可。谢谢@Fabian。我开始尝试返回异步任务
,但由于某种原因,它没有序列化。仔细想想,这可能是因为Accept头。哦,你的解决方案是显而易见的,它是成功的。
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code/>
<m:message xml:lang="en-US">An error has occurred.</m:message>
<m:innererror>
<m:message>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.
</m:message>
<m:type>System.InvalidOperationException</m:type>
<m:stacktrace/>
<m:internalexception>
<m:message>Cannot serialize a null 'feed'.</m:message>
<m:type>
System.Runtime.Serialization.SerializationException
</m:type>
<m:stacktrace>
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.WebHost.HttpControllerHandler.
<WriteBufferedResponseContentAsync>d__1b.MoveNext()
</m:stacktrace>
</m:internalexception>
</m:innererror>
</m:error>
queryOptions.ApplyTo(result.AsQueryable()) as IQueryable<Cars>
[EnableQuery(HandleNullPropagation = HandleNullPropagationOption.True)]
public async Task<IQueryable<Cars>> GetCars(ODataQueryOptions<Cars> queryOptions)
{
// validate the query.
try
{
queryOptions.Validate(_validationSettings);
}
catch (ODataException ex)
{
throw new HttpRequestException(ex.Message);
}
var result = await _context.GetCarsAsync();
return result.AsQueryable();
}
[EnableQuery]
public async Task<IQueryable<Cars>> GetCars()
{
// return IQueryable<Cars> from context, do not perform request to database
return await Task.FromResult(_context.GetCarsQuery());
}