gpt4 book ai didi

asp.net-web-api - OData V4修改服务器端$filter

转载 作者:行者123 更新时间:2023-12-02 07:18:13 24 4
gpt4 key购买 nike

我希望能够修改 Controller 内的过滤器,然后根据更改后的过滤器返回数据。

因此,我在服务器端有一个 ODataQueryOptions 参数,可以使用它来查看 FilterQueryOption。

假设过滤器类似于“$filter=ID eq -1”,但在服务器端,如果我看到 ID 为“-1”,这告诉我用户想要选择所有记录。

我尝试将“$filter=ID eq -1”更改为“$filter=ID ne -1”,这将通过设置 Filter.RawValue 为我提供所有内容,但这是只读的。
我尝试创建一个新的 FilterQueryOption 但这需要 ODataQueryContext 和 ODataQueryOptionParser 我不知道如何创建。

然后我尝试设置 Filter = Null,然后使用 ApplyTo,当我在 Controller 中设置断点并在立即窗口上检查它时,它似乎可以工作,但是一旦它将 GET 方法留在 Controller 上,那么它“恢复”回到 URL 中传递的内容。

本文讨论了做一些非常类似“The best way to modify a WebAPI OData QueryOptions.Filter”的事情,但是一旦它离开 Controller GET 方法,它就会恢复到 URL 查询过滤器。

使用示例代码更新

[EnableQuery]
[HttpGet]
public IQueryable<Product> GetProducts(ODataQueryOptions<Product> queryOptions)
{
if (queryOptions.Filter != null)
{
var url = queryOptions.Request.RequestUri.AbsoluteUri;
string filter = queryOptions.Filter.RawValue;

url = url.Replace("$filter=ID%20eq%201", "$filter=ID%20eq%202");
var req = new HttpRequestMessage(HttpMethod.Get, url);

queryOptions = new ODataQueryOptions<Product>(queryOptions.Context, req);
}

IQueryable query = queryOptions.ApplyTo(db.Products.AsQueryable());
return query as IQueryable<Product>;
}

运行此代码不会返回任何产品,这是因为 URL 中的原始查询需要产品 1,而我将产品 1 的 ID 过滤器交换为产品 2。
现在,如果我运行 SQL Profiler,我可以看到它添加了类似“Select * from Product WHERE ID = 1 AND ID = 2”的内容。

但是如果我通过替换 $top 来尝试同样的事情,那么它就可以正常工作。

[EnableQuery]
[HttpGet]
public IQueryable<Product> GetProducts(ODataQueryOptions<Product> queryOptions)
{
if (queryOptions.Top != null)
{
var url = queryOptions.Request.RequestUri.AbsoluteUri;
string filter = queryOptions.Top.RawValue;

url = url.Replace("$top=2", "$top=1");
var req = new HttpRequestMessage(HttpMethod.Get, url);

queryOptions = new ODataQueryOptions<Product>(queryOptions.Context, req);
}

IQueryable query = queryOptions.ApplyTo(db.Products.AsQueryable());
return query as IQueryable<Product>;
}

最终结果
在微软的帮助下。这是支持过滤、计数和分页的最终输出。

using System.Net.Http;
using System.Web.OData;
using System.Web.OData.Extensions;
using System.Web.OData.Query;

/// <summary>
/// Used to create custom filters, selects, groupings, ordering, etc...
/// </summary>
public class CustomEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
IQueryable result = default(IQueryable);

// get the original request before the alterations
HttpRequestMessage originalRequest = queryOptions.Request;

// get the original URL before the alterations
string url = originalRequest.RequestUri.AbsoluteUri;

// rebuild the URL if it contains a specific filter for "ID = 0" to select all records
if (queryOptions.Filter != null && url.Contains("$filter=ID%20eq%200"))
{
// apply the new filter
url = url.Replace("$filter=ID%20eq%200", "$filter=ID%20ne%200");

// build a new request for the filter
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, url);

// reset the query options with the new request
queryOptions = new ODataQueryOptions(queryOptions.Context, req);
}

// set a top filter if one was not supplied
if (queryOptions.Top == null)
{
// apply the query options with the new top filter
result = queryOptions.ApplyTo(queryable, new ODataQuerySettings { PageSize = 100 });
}
else
{
// apply any pending information that was not previously applied
result = queryOptions.ApplyTo(queryable);
}

// add the NextLink if one exists
if (queryOptions.Request.ODataProperties().NextLink != null)
{
originalRequest.ODataProperties().NextLink = queryOptions.Request.ODataProperties().NextLink;
}
// add the TotalCount if one exists
if (queryOptions.Request.ODataProperties().TotalCount != null)
{
originalRequest.ODataProperties().TotalCount = queryOptions.Request.ODataProperties().TotalCount;
}

// return all results
return result;
}
}

最佳答案

删除 [EnableQuery] 属性,您的方案应该可以工作,因为使用此属性后,OData/WebApi 将在您在 Controller 中返回数据后应用您的原始查询选项,如果您已经在 Controller 方法中应用,那么您不应该使用该属性。

但是如果你的查询选项包含$select,这些代码就不起作用,因为结果的类型不是Product,我们使用包装器来表示$select的结果,所以我建议你使用尝试这个:

创建自定义的EnableQueryAttribute

public class MyEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
if (queryOptions.Filter != null)
{
queryOptions.ApplyTo(queryable);
var url = queryOptions.Request.RequestUri.AbsoluteUri;

url = url.Replace("$filter=Id%20eq%201", "$filter=Id%20eq%202");
var req = new HttpRequestMessage(HttpMethod.Get, url);

queryOptions = new ODataQueryOptions(queryOptions.Context, req);
}

return queryOptions.ApplyTo(queryable);
}
}

在 Controller 方法中使用此属性

[MyEnableQueryAttribute]
public IHttpActionResult Get()
{
return Ok(_products);
}

希望能解决您的问题,谢谢!

风扇。

关于asp.net-web-api - OData V4修改服务器端$filter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33660648/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com