ASP.NET Coreでクエリ文字列から値を読み取る方法は?


135

ASP.NET Core MVCを使用してRESTful APIを1つ構築しています。クエリ文字列パラメーターを使用して、コレクションを返すリソースのフィルタリングとページングを指定します。

その場合、クエリ文字列で渡された値を読み取って、フィルター処理を行い、返される結果を選択する必要があります。

コントローラーGetアクション内でアクセスするとHttpContext.Request.Query1が返されることはすでにわかっていますIQueryCollection

問題は、値を取得するためにそれがどのように使用されるのかわからないことです。実は、私は、例えば、

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

問題はHttpContext.Request.Query["page"]、文字列ではなくStringValues

とにかく、IQueryCollectionクエリ文字列の値を実際に読み取るにはどうすればよいですか?


1
私はあなたがここで見つけることができます同じのための記事を書いた:neelbhatt40.wordpress.com/2017/07/06/...
ニール

回答:


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
(Name = "page")は不要です-同じ名前を付けた場合、変数にバインドされます
a3uge

これは、クエリ文字列パラメーター名が構造化されている場合に重要です。たとえば、「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は必要ありません。あなたは文字列にクエリ値を割り当てた場合、コンパイラは、暗黙的にキャストされます...
ステファン・スタイガー

26

ASP.NETコアは自動的に結合する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規約を変更しない場合、example.com
[controller] / [action] / {someid:int}?someparameter

19

これが私が使用したコードサンプルです(.NET Coreビューで):

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

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

2
FULLオブジェクト名(または正しい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 2018

将来の読者:完全修飾名 "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

.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

私はこの問題のより良い解決策を持っています、

  • リクエストは抽象クラス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.