【问题标题】:Filter by query string dynamically in MVC Core?在 MVC Core 中按查询字符串动态过滤?
【发布时间】:2019-02-23 01:44:30
【问题描述】:

我有一个这样的get方法...

[HttpGet]
public async Task<ActionResult<IEnumerable<Customer>>> GetCustomers()
{
    var queryString = HttpContext.Request.Query;
    return await _context.Customers.Take(7).ToListAsync();
}

我想传入这样的查询字符串:

https://localhost:44315/api/customer?param1=1&param2=String Value

我想这样做,而不必在我的参数列表中声明每个参数。例如

[HttpGet]
public async Task<ActionResult<IEnumerable<Customer>>> GetCustomers(int param1, string param2)
{
    var queryString = HttpContext.Request.Query;
    return await _context.Customers.Take(7).ToListAsync();
}

我想避免这样做,因为我的类有几十个参数。我知道您可以使用 [FromQuery] Customer customer 进行绑定,但我认为这不是我想要的。

有没有办法动态地做到这一点?

【问题讨论】:

  • [FromQuery] Dictionary&lt;string, string&gt; 呢?

标签: c# query-string asp.net-core-webapi


【解决方案1】:

我最终做了这样的事情

   //GET: api/customer
    [HttpGet]
    public async Task<ActionResult<IEnumerable<Customer>>> GetCustomers()
    {
        var queryParams = HttpContext.Request.Query;
        var collection = _context.Customers.FilterByQueryParams(queryParams);
        return await Task.FromResult(collection.ToList());
    }

然后在一个单独的类中

public static class DynamicFilterExtensionMethods
{
    public static IEnumerable<T> FilterByQueryParams<T>(this IEnumerable<T> collection, IQueryCollection queryParams) where T : new()
    {
        var classType = typeof(T);
        var propList = classType.GetProperties();
        //accountNumber ==> accountNumber, AccountNumber ==> accountNumber
        var props = new Dictionary<string, PropertyInfo>(propList.Select(x => new KeyValuePair<string, PropertyInfo>(Char.ToLowerInvariant(x.Name[0]) + x.Name.Substring(1), x)));

        foreach (var param in queryParams) {
            if (props.ContainsKey(param.Key)) {
                var prop = props[param.Key];
                   if (prop.PropertyType.IsPrimitive) {
                    if (param.Value.Count == 1)
                    {
                        collection = collection.Where(x => prop.GetValue(x, null).ToString() == param.Value.First());
                    }
                    else {
                        var aggregate = new List<T>();
                        foreach (var value in param.Value) {
                            aggregate = aggregate.Union<T>(collection.Where(x => prop.GetValue(x, null).ToString() == value)).ToList();
                        }
                        collection = aggregate.AsEnumerable();
                    }
                }
            }
        }

        return collection;
    }
}

这里还有很多工作要做,但我认为这是一个好的开始。

【讨论】:

    【解决方案2】:

    如果您只想通过 HttpContext 访问查询参数而忘记操作参数,则可以完全省略参数。 ASP.NET Core 不会将查询字符串作为操作路由的一部分进行评估(这也意味着您不能基于查询参数创建重载,除非您通过属性路由指定不同的路由)。

    【讨论】:

    • 投反对票可能是有道理的,但如果你至少添加一条评论来解释你投反对票的原因为什么会很好。
    • 不是我:P 我确实认为 [FromQuery] Dictionary 或我上面的查询代码几乎可以完成同样的事情。我真的不知道我在这里希望什么。
    • 我没想到是你 :) 很高兴你找到了一些可能对你有用的选项。
    • 你试过 var param1 = HttpContext.Current.Request.QueryString["param1"] 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2016-07-16
    相关资源
    最近更新 更多