如何使用ASP.NET Core从查询字符串读取值?


135

我正在使用ASP.NET Core MVC构建一个RESTful API,并且我想使用querystring参数来指定对返回集合的资源的过滤和分页。

在那种情况下,我需要读取在querystring中传递的值以进行过滤并选择要返回的结果。

我已经发现在控制器Get动作内部访问HttpContext.Request.Query返回一个IQueryCollection

问题是我不知道如何使用它来检索值。实际上,我认为该方法是通过使用例如

string page = HttpContext.Request.Query["page"]

问题是HttpContext.Request.Query["page"]它不会返回字符串,而是返回StringValues

无论如何,如何使用IQueryCollection来实际读取查询字符串值?


1
我写了一篇相同的文章,您可以在这里找到:neelbhatt40.wordpress.com/2017/07/06/…–
Neel

Answers:


134

您可以使用 [FromQuery]用来将特定模型绑定到查询字符串:

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/model-binding

例如

[HttpGet()]
public IActionResult Get([FromQuery(Name = "page")] string page)
{...}

5
我认为[FromQuery]attrib也可以省略,因为.net绑定默认会检查所有表单输入和url querystring参数,除了您出于某些原因限制其来源。
S.Serpooshan

12
(名称=“页面”)是不必要的-它会结合到可变如果命名相同
a3uge

如果querystring参数名称是结构化的,这一点很重要。例如“object.propname”
何塞Capistrano的

95

IQueryCollection如果page指定了单个参数,则可以使用ToString方法,该方法将在其上返回所需的值:

string page = HttpContext.Request.Query["page"].ToString();

如果有多个类似?page=1&page=2的值,那么ToString调用的结果将是1,2

但是正如@ mike-g在他的答案中建议的那样,您最好使用模型绑定,而不是直接访问该HttpContext.Request.Query对象。


6
ToString是不必要的。编译器会隐式转换它,如果你的查询值赋给一个字符串..
斯特凡·斯泰格尔

26

ASP.NET Core将自动绑定form valuesroute values并按query strings名称绑定。这意味着您可以简单地做到这一点:

[HttpGet()]
public IActionResult Get(int page)
{ ... }

MVC将尝试按名称将请求数据绑定到操作参数...下面是数据源的列表,按照模型绑定通过它们查找的顺序

  1. Form values:这些是使用POST方法进入HTTP请求的表单值。(包括jQuery POST请求)。

  2. Route values:路由提供的一组路由值

  3. Query strings:URI的查询字符串部分。

资料来源:模型绑定如何工作


仅供参考,您还可以结合使用自动方法和显式方法:

[HttpGet()]
public IActionResult Get(int page
     , [FromQuery(Name = "page-size")] int pageSize)
{ ... }

20

您可以像这样创建一个对象:

public class SomeQuery
{
    public string SomeParameter { get; set; }
    public int? SomeParameter2 { get; set; }
}

然后在控制器中进行如下操作:

[HttpGet]
public IActionResult FindSomething([FromQuery] SomeQuery query)
{
    // Your implementation goes here..
}

更好的是,您可以通过以下方式创建API模型:

[HttpGet]
public IActionResult GetSomething([FromRoute] int someId, [FromQuery] SomeQuery query)

至:

[HttpGet]
public IActionResult GetSomething(ApiModel model)

public class ApiModel
{
    [FromRoute]
    public int SomeId { get; set; }
    [FromQuery]
    public string SomeParameter { get; set; }
    [FromQuery]
    public int? SomeParameter2 { get; set; }
}

这将应用于什么URL?我是新来的,所以我不能“反向工程”到URL。会像example.com/somequery/…吗?
基督教徒

1
@Christian,如果您不更改任何约定,
则为

19

这是我使用过的代码示例(带有.NET Core视图):

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

    if (Context.Request.Query.TryGetValue("yourKey", out queryVal) &&
        queryVal.FirstOrDefault() == "yourValue")
    {
    }
}

2
支持包括FULL对象名称(或正确的using语句)。当人们只输入没有完全限定的对象名称或至少没有using语句时,我会大为震惊。谢谢。
granadaCoder

11

StringValues是一个字符串数组。您可以通过提供索引来获取字符串值,例如HttpContext.Request.Query["page"][0]


1
谢谢; 这是唯一回答问题的答案。(就我而言,我不能使用绑定,因为我有一个更复杂的逻辑,例如“首先尝试查询字符串,如果缺少,请尝试会话,依此类推。”)
Marcel Popescu

7

IQueryCollection上面有一个TryGetValue()用给定键返回值的值。因此,如果您有一个名为的查询参数someInt,则可以这样使用它:

var queryString = httpContext.Request.Query;
StringValues someInt;
queryString.TryGetValue("someInt", out someInt);
var daRealInt = int.Parse(someInt);

请注意,除非您有多个具有相同名称的参数,否则StringValues类型不是问题。


要添加到此答案,如果调用StringValues.ToString(),则可以将其直接转换为字符串(如果需要)。
eltiare

将来的读者:完全合格的名称“ Microsoft.AspNetCore.Http.IQueryCollection queryString = this.Request.Query;” 我的位置在“ Assembly Microsoft.AspNetCore.Http.Features,版本= 3.1.0.0”和“ Microsoft.Extensions.Primitives.StringValues”中(我的位置在“ Assembly Microsoft.Extensions.Primitives,版本= 3.1.2.0”中)
granadaCoder

3

在.net核心中,如果您想在我们的视图中访问querystring,请像

@Context.Request.Query["yourKey"]

如果我们位于@Context不适合使用的位置,则可以将其注入

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@if (HttpContextAccessor.HttpContext.Request.Query.Keys.Contains("yourKey"))
{
      <text>do something </text>
}

也用于饼干

HttpContextAccessor.HttpContext.Request.Cookies["DeniedActions"]

2
不需要所有这些代码。只需使用@ Context.Request.Query [“ yourKey”]
Shadi Namrouti,

是的@ShadiNamrouti您认为\ @Context合适,我们可以像\ @ Context.Request.Query [“ yourKey”]一样使用它,但是如果我们在控制器中,则需要注入HttpContextAccessor.HttpContext。
M.Ali El-Sayed

2

对于这个问题,我有更好的解决方案,

  • request是抽象类ControllerBase的成员
  • GetSearchParams()是在波纹管帮助器类中创建的扩展方法。

var searchparams = await Request.GetSearchParams();

我用很少的扩展方法创建了一个静态类

public static class HttpRequestExtension
{
  public static async Task<SearchParams> GetSearchParams(this HttpRequest request)
        {
            var parameters = await request.TupledParameters();

            try
            {
                for (var i = 0; i < parameters.Count; i++)
                {
                    if (parameters[i].Item1 == "_count" && parameters[i].Item2 == "0")
                    {
                        parameters[i] = new Tuple<string, string>("_summary", "count");
                    }
                }
                var searchCommand = SearchParams.FromUriParamList(parameters);
                return searchCommand;
            }
            catch (FormatException formatException)
            {
                throw new FhirException(formatException.Message, OperationOutcome.IssueType.Invalid, OperationOutcome.IssueSeverity.Fatal, HttpStatusCode.BadRequest);
            }
        }



public static async Task<List<Tuple<string, string>>> TupledParameters(this HttpRequest request)
{
        var list = new List<Tuple<string, string>>();


        var query = request.Query;
        foreach (var pair in query)
        {
            list.Add(new Tuple<string, string>(pair.Key, pair.Value));
        }

        if (!request.HasFormContentType)
        {
            return list;
        }
        var getContent = await request.ReadFormAsync();

        if (getContent == null)
        {
            return list;
        }
        foreach (var key in getContent.Keys)
        {
            if (!getContent.TryGetValue(key, out StringValues values))
            {
                continue;
            }
            foreach (var value in values)
            {
                list.Add(new Tuple<string, string>(key, value));
            }
        }
        return list;
    }
}

通过这种方式,您可以轻松访问所有搜索参数。我希望这会对很多开发人员有所帮助:)


我是否缺少某些内容-在哪里定义了FhirException,在其中找到了Task <SearchParams>哪个名称空间?
道格·汤普森

1

一些评论也提到了这一点,但是asp net core可以为您完成所有这些工作。

如果查询字符串与名称匹配,则它将在控制器中可用。

https:// myapi / some-endpoint / 123?someQueryString = YayThisWorks

[HttpPost]
[Route("some-endpoint/{someValue}")]
public IActionResult SomeEndpointMethod(int someValue, string someQueryString)
    {
        Debug.WriteLine(someValue);
        Debug.WriteLine(someQueryString);
        return Ok();
    }

123

YayThisWorks

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.