ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

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

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

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


o
ono2012

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

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

例如

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

我认为 [FromQuery] 属性也可以省略,因为默认情况下 .net 绑定将检查所有表单输入和 url 查询字符串参数,除非您有某些理由限制其来源。
(Name = "page") 是不必要的 - 如果名称相同,它将绑定到变量
如果查询字符串参数名称是结构化的,这很重要。例如'object.propname'
D
Darin Dimitrov

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

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

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

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


ToString 不是必需的。如果您将查询值分配给字符串,编译器将隐式转换它。
添加 ToString() 甚至是危险的。如果 URL 没有查询字符串 ID,则返回值为 null(docs.microsoft.com/en-us/dotnet/api/…) 并导致 NullReference 异常。
s
spottedmahn

ASP.NET Core 将自动按名称绑定 form valuesroute valuesquery 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)
{ ... }

虽然不是操作员问题的答案,但对于出于类似原因来到这里的人来说,这是一个非常有用的答案。
P
Pierre Arnaud

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

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

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

赞成包含完整的对象名称(或正确的 using 语句)。当人们只输入没有完全限定或至少使用语句的对象名时,我会发疯。谢谢。
M
Mariusz

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

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/… 吗?
@Christian,如果您不更改任何约定,它将是 example.com/[controller]/[action]/{someid:int}?someparameter=1&someparameter2=2
M
MD. Khairul Basar

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


谢谢;这是唯一真正回答了这个问题的回答。 (在我的情况下,我不能使用绑定,因为我有一个更复杂的逻辑,例如“首先尝试查询字符串,如果缺少尝试会话等等”。)
s
steamrolla

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

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

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


要添加到此答案,如果您调用 StringValues.ToString() ,则可以根据需要将其直接转换为字符串。
未来的读者:完全限定名称“Microsoft.AspNetCore.Http.IQueryCollection queryString = this.Request.Query;”我的是“Assembly Microsoft.AspNetCore.Http.Features, Version=3.1.0.0”和“Microsoft.Extensions.Primitives.StringValues”(我的是“Assembly Microsoft.Extensions.Primitives, Version=3.1.2.0”)
M
M.Ali El-Sayed

在 .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"]

不需要所有的代码。只需使用 @Context.Request.Query["yourKey"]
是的@ShadiNamrouti,你是正确的,因为 \@Context 是可用的,我们可以像 \@Context.Request.Query["yourKey"] 一样使用它,但如果我们在控制器中,我们需要注入 HttpContextAccessor.HttpContext。
S
Sinan Dogan

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

看法:

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

Startup.cs 配置服务:

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

S
Shanjee

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

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

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


我错过了什么 - FhirException 定义在哪里, Task 在什么命名空间中找到?
J
Jordan Ryder

一些评论也提到了这一点,但是 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


Z
Zanyar J.Ahmed

Startup.cs 添加这个服务 services.AddSingleton();您的视图添加注入 @inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor 获取您的价值

代码

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

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

C
CodingYourLife

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

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor

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