如何从查询字符串读取值与ASP。网络核心?

我正在使用ASP构建一个RESTful API。NET Core MVC和我想使用查询字符串参数来指定对返回集合的资源进行过滤和分页。

在这种情况下,我需要读取在查询字符串中传递的值以过滤并选择要返回的结果。

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

问题是我不知道如何使用它来检索值。事实上,我认为这样做的方法是使用,例如

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

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

不管怎样,如何使用IQueryCollection来实际读取查询字符串值呢?

389094 次浏览

你可以使用[FromQuery]将一个特定的模型绑定到查询字符串:

https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding

如。

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

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

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

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

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

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

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

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

下面是我使用的一个代码示例(带有。net Core视图):

@{
Microsoft.Extensions.Primitives.StringValues queryVal;


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

ASP。NET Core会自动按名称绑定form valuesroute valuesquery strings。这意味着你可以简单地这样做:

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

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

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

  2. Route values:路由提供的路由值集

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

来源:在ASP中绑定模型。网络核心


供你参考,你也可以结合自动和显式方法:

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

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

在。net core中,如果你想在视图中访问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"]

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

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; }
}

我有个更好的解决办法,

  • request是一个抽象类ControllerBase的成员
  • GetSearchParams()是在bellow helper中创建的扩展方法 李课。< / >

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;
}
}

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

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

如果您有一个与名称匹配的查询字符串,它将在控制器中可用。

< a href = " https://myapi/some-endpoint/123?someQueryString=YayThisWorks" rel="nofollow noreferrer">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

也许有用。 在视图中获取查询字符串参数

观点:

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@{ Context.Request.Query["uid"]}

Startup.cs配置服务:

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
  1. Startup.cs添加服务 李services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); < / >
  2. 你的视图添加注入 @inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
  3. 获得你的价值

代码

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@{
var id = HttpContextAccessor.HttpContext.Request.RouteValues["id"];


if (id != null)
{
// parameter exist in your URL
}
}

如果你想在asp.net核心视图中访问QueryString,你可以这样做:

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor


@if (Context.Request.Query.Keys.Any())
{
<button>--ClearFilters--</button>
}