我正在实现一个 Web API 接口来支持一些相当复杂的查询来运行它,并且遇到了最大请求 URI 长度的问题。
我的 Web API 方法的定义如下所示(使用 Automapper 执行 DTO 投影):
public IQueryable<ReportModel> Get(ODataQueryOptions<Report> queryOptions)
{
var query = DbContext.Query<Report>();
return (queryOptions.ApplyTo(query) as IQueryable<Report>).WithTranslations().Project(MappingEngine).To<ReportModel>().WithTranslations();
}
我的请求由动态构建的 OData 查询组成,其中包括可能大量的“Field eq Id”过滤器,这些过滤器被捕获到 ODataQueryOptions 参数中,然后应用于 IQueryable 数据库上下文。例如:
http://example.com/api/Report?$filter=(Field1+eq+1%20or%20Field1+eq+5%20or%20Field1+eq+10%20or%20Field1+eq+15...
一旦请求 URI 的长度达到一定限制,就会出现此问题。任何 URI 长度超过该限制的请求都会导致 404 错误。经过一些测试,此限制似乎在 2KB 范围内(具有 2065 个字符的 URI 工作正常,而具有 2105 个字符的 URI 在 Chrome、IE 或 FF 中则失败)。
对此的简单解决方案似乎是将请求类型从 GET 更改为 POST 请求,在正文中发送搜索查询,而不是在 URI 中发送。然而,我在尝试使其正常工作时遇到了一些问题,因为我似乎无法从 POST 请求中正确填充 ODataQueryOptions 对象。我的 Web API 方法现在如下所示:
public IQueryable<ReportModel> Post([FromBody] ODataQueryOptions<Report> queryOptions)
{
var query = DbContext.Query<Report>();
return (queryOptions.ApplyTo(query) as IQueryable<Report>).WithTranslations().Project(MappingEngine).To<ReportModel>().WithTranslations();
}
正如您所看到的,我尝试从请求正文而不是从 URI 填充查询选项。到目前为止,我还无法从请求中获取要填充的 ODataQueryOptions 参数,并且该参数结果为“null”。如果我删除“[FromBody]”属性,查询选项对象将从请求 URI 中正确填充,但同样的 URI 长度问题仍然存在。
以下是我如何从浏览器调用该方法的示例(使用 jQuery):
$.ajax({
url: "/API/Report",
type: "POST",
data: ko.toJSON({
'$filter': 'Field1+eq+1%20or%20Field1+eq+5%20or%20Field1+eq+10%20or%20Field1+eq+15...'
}),
dataType: "json",
processData: false,
contentType: 'application/json; charset=utf-8',
});
首先,是否可以执行我在这里尝试执行的操作(在请求正文中发布 ODataQueryOptions)?如果是这样,我是否正确构建了 POST 请求?我还缺少什么吗?