我正在使用 ASP.NET Core MVC 构建一个 RESTful API,并且我想使用查询字符串参数来指定对返回集合的资源进行过滤和分页。
在这种情况下,我需要读取查询字符串中传递的值以过滤并选择要返回的结果。
我已经发现在控制器 Get
操作中访问 HttpContext.Request.Query
会返回一个 IQueryCollection
。
问题是我不知道它是如何用于检索值的。事实上,我认为这样做的方法是使用,例如
string page = HttpContext.Request.Query["page"]
问题是 HttpContext.Request.Query["page"]
不返回字符串,而是返回 StringValues
。
无论如何,如何使用 IQueryCollection
来实际读取查询字符串值?
您可以使用 [FromQuery]
将特定模型绑定到查询字符串:
https://docs.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
对象。
ASP.NET Core 将自动按名称绑定 form values
、route values
和 query strings
。这意味着您可以简单地执行以下操作:
[HttpGet()]
public IActionResult Get(int page)
{ ... }
MVC 将尝试按名称将请求数据绑定到操作参数...下面是数据源列表,按模型绑定查看它们的顺序排列表单值:这些是使用 POST 方法进入 HTTP 请求的表单值. (包括 jQuery POST 请求)。路由值:路由提供的路由值集合 查询字符串:URI 的查询字符串部分。
来源:Model Binding in ASP.NET Core
仅供参考,您还可以结合自动和显式方法:
[HttpGet()]
public IActionResult Get(int page
, [FromQuery(Name = "page-size")] int pageSize)
{ ... }
这是我使用过的代码示例(带有 .NET Core 视图):
@{
Microsoft.Extensions.Primitives.StringValues queryVal;
if (Context.Request.Query.TryGetValue("yourKey", out queryVal) &&
queryVal.FirstOrDefault() == "yourValue")
{
}
}
您可以像这样创建一个对象:
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; }
}
StringValues
是一个 array of strings。您可以通过提供索引来获取您的字符串值,例如 HttpContext.Request.Query["page"][0]
。
IQueryCollection
上有一个 TryGetValue()
,它返回具有给定键的值。因此,如果您有一个名为 someInt
的查询参数,您可以像这样使用它:
var queryString = httpContext.Request.Query;
StringValues someInt;
queryString.TryGetValue("someInt", out someInt);
var daRealInt = int.Parse(someInt);
请注意,除非您有多个同名参数,否则 StringValues
类型不是问题。
在 .net 核心中,如果您想在我们的视图中访问查询字符串,请使用它
@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"]
也许它有帮助。在视图中获取查询字符串参数
看法:
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@{ Context.Request.Query["uid"]}
Startup.cs 配置服务:
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
对于这个问题,我有更好的解决方案,
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 为您完成了所有这些工作。
如果您有一个与名称匹配的查询字符串,它将在控制器中可用。
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
Startup.cs 添加这个服务 services.AddSingleton
代码
@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>
}
不定期副业成功案例分享
[FromQuery]
属性也可以省略,因为默认情况下 .net 绑定将检查所有表单输入和 url 查询字符串参数,除非您有某些理由限制其来源。