ASP.NET Core를 사용하여 쿼리 문자열에서 값을 읽는 방법은 무엇입니까?


135

ASP.NET Core MVC를 사용하여 하나의 RESTful API를 작성 중이며 querystring 매개 변수를 사용하여 컬렉션을 반환하는 리소스에 대한 필터링 및 페이징을 지정하려고합니다.

이 경우 쿼리 문자열에 전달 된 값을 읽어서 필터링 할 결과를 선택해야합니다.

컨트롤러 Get액션에 액세스 하면 HttpContext.Request.Queryone 반환 한다는 것을 이미 알았습니다 IQueryCollection.

문제는 값을 검색하는 데 어떻게 사용되는지 모른다는 것입니다. 사실, 나는하는 방법이 예를 들어

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

문제는 HttpContext.Request.Query["page"]문자열을 반환하지 않지만 a StringValues입니다.

어쨌든 어떻게 IQueryCollection실제로 쿼리 문자열 값을 읽는 데 사용 합니까?


1
나는 당신이 여기에서 찾을 수있는 같은 게시물을 썼습니다 : neelbhatt40.wordpress.com/2017/07/06/…
Neel

답변:


134

[FromQuery]특정 모델을 쿼리 문자열에 바인딩하는 데 사용할 수 있습니다 .

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

예 :

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

5
[FromQuery].net 바인딩이 기본적으로 모든 양식 입력과 URL 쿼리 문자열 매개 변수를 검사하므로 소스를 제한 해야하는 이유가 있다는 점을 제외하고 attrib도 생략 할 수 있다고 생각합니다 .
S.Serpooshan

12
(명 = "페이지")는 불필요 - 동일한 경우라는 변수에 바인딩
a3uge

querystring 매개 변수 이름이 구조화 된 경우 중요합니다. 예를 들어 'object.propname'의 경우
호세 카피 스트라 노

96

IQueryCollection단일 page매개 변수가 지정된 경우 원하는 값을 리턴 하는 ToString 메소드를 사용할 수 있습니다 .

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

여러 값 ?page=1&page=2이있는 경우 ToString 호출의 결과는1,2

그러나 @ mike-g가 그의 대답에서 제안한 것처럼 HttpContext.Request.Query객체를 직접 액세스하지 않고 모델 바인딩을 사용하는 것이 좋습니다 .


6
ToString은 필요하지 않습니다. 쿼리 값을 문자열에 할당하면 컴파일러에서 암시 적으로 캐스트합니다.
Stefan Steiger

26

ASP.NET 코어가 자동으로 바인딩 form values, route 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/… 와 같은 것 입니까?
Christian

1
@Christian 규칙을 변경하지 않으면 example.com/[controller]/[action]/{someid:int}?someparameter=1&someparameter2=2
LxL

19

다음은 .NET Core 뷰와 함께 사용한 코드 샘플입니다.

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

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

2
FULL 오브젝트 이름 포함 (또는 올바른 using 문)에 대한 의견을 개진하십시오. 사람들이 완전히 qualfied하지 않거나 최소한 using 문을 사용하여 객체 이름을 넣을 때 나를 미치게합니다. 감사.
granadaCoder

11

StringValues문자열 배열 . 색인을 제공하여 문자열 값을 얻을 수 있습니다 (예 :) HttpContext.Request.Query["page"][0].


1
감사합니다; 이것이 실제로 질문에 대답 한 유일한 응답이었습니다. (필자의 경우, "쿼리 문자열을 먼저 시도해보십시오. 세션이 누락 된 경우 등"과 같은보다 복잡한 논리를 가지고 있기 때문에 바인딩을 사용할 수 없습니다.)
Marcel Popescu

7

IQueryCollectionTryGetValue()주어진 키로 값을 반환 하는 on이 있습니다. 따라서이라는 검색어 매개 변수가있는 경우 다음 someInt과 같이 사용할 수 있습니다.

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

같은 이름의 여러 매개 변수 StringValues가 없으면 유형에 문제가 없습니다.


이 답변에 추가하기 위해 StringValues.ToString ()을 호출하면 필요한 경우 문자열로 직접 캐스트 할 수 있습니다.
eltiare 2019

미래 독자 : 정규화 된 이름 "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")에있었습니다.
granadaCoder

3

뷰에서 querystring에 액세스하려면 .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"]

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>는 어떤 네임 스페이스를 찾을 수 있습니까?
Doug Thompson – DouggyFresh

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.