ASP.NET WebAPIでURLパラメーターを受け取る

URLパラメータ*1は、URLの最後に以下のように加えられた変数を指します。

https://localhost:8080/app/v1/data?code=100

この「code=100」の部分を ASP.NET Core Web API で受け取る方法です。

確認環境

  • .NET 6 + ASP.NET Core Web API
  • VisualStudio 2022
  • Windows 11

URLパラメーターを受け取る

引数に「FromQuery」属性を指定します。

using System;
using Microsoft.AspNetCore.Mvc;

// ★例えば以下の指定から
// https://localhost:8080/app/v1/data?code=100
//  → code=100を受け取りたい

[Route("app/v1")]
public class SampleV1Controller : ControllerBase
{
    [HttpGet("data")]
    public IActionResult GetData([FromQuery] string code) // FromQuery属性で受け取れる
    {
        Log.Trace($"code={code}");
        
        if(int.TryParse(code, out int _code))
        {
            Log.Trace($"_code={_code}"); // 一旦文字列で受けて自分で変換処理を書いたほうが良い
        }
        
        return this.Ok();
    }
}

// FromQueryのNameを指定すれば別の引数名でも受け取れる
public IActionResult PostStatus([FromQuery(Name ="code")] string hoge)

// null許容型で受け取るのも悪くない
//   → dataがintに変換できない値を受け取るとnullになる
public IActionResult PostStatus([FromQuery] int? data)

文字列で受け取って自分で変換処理を書くか、null 許容型で受け取るのが推奨です。

null 許容型「でない」指定は、Web サーバーがパラメータを int に変換できない場合メソッドに入らず自動で404となります。サーバー側のログに履歴は残りますが、何が起きたのかプログラム側では状況を判断できないので、string もしくは null 許容型を指定しましょう。

また、パラメーターがオプションで省略される場合も、未指定 = null とすれば扱いやすいです。

string でパラメータを受け取る場合、APIで受け取ったけど、int に変換できない(=ユーザーの指定内容が違う)処理がハンドリングできます。null 許容型の場合、受け取れたかどうかの null 判定後に int への処理を省略出来て少し楽です。どちらを選択するかは状況に依ります。

複数パラメータを受け取る

複数のパラメーターを受け取る方法は2種類あります。

ひとつ目:単純に引数に並べる

// 複数個のパラメーター指定
// ~/app/v1//data?code=100&id=hoge

[HttpGet("data")]
public IActionResult PostStatus([FromQuery] string data, [FromQuery] int? id)

ふたつ目:クラスを定義して受け取る

以下のように複合型のクラスを作成して引数に指定します。

// パラメーター用の複合型のクラスを用意する
public class UrlParam
{
    [FromQuery(Name = "code")] // プロパティに属性を指定する
    public string Code { get; set; }

    [FromQuery(Name = "id")]
    public int? ID { get; set; }
}

[HttpGet("data")]
public IActionResult PostStatus(UrlParam param)
{
    param.Code; // 100
    param.ID; //null
}

クラスのプロパティに「FromQuery」属性を指定しておいて引数に指定すれば自動的にマッピングされます。インスタスは自動で作成されます。

基本的に、複数のパラメーターを受け取る時は、ふたつ目のクラス化しておいた方がよいです。変換できるかどうかや、組み合わせが正当かどうかはパラメータークラスに実装するとメソッド内をクリーンな状態に保ちやすいです。

メソッドの引数以外からURLパラメーターを受け取る

必ず属性を付けてメソッドの引数から受け取らなくてもURLで指定されたパラメーターは受け取ることができます。

ControllerBase を継承しているので引数に指定してないパラメーターも実際は WebAPI が処理を開始した時点で受け取れています。

// (1)こんな感じで定義してあったとして
[HttpHet("sample")
public IActionResult Hoge([FromQuery(Name = "arg1")] string arg1)

// (2)以下のようにリクエストを投げたとする
// localhost:8080/sample?arg1=001&arg2=002

この場合arg1="001"は引数で受け取れます。

それ以外のパラメータは無視されますが、受け取っているため以下のように取得できます。

public IActionResult Hoge([FromQuery(Name = "arg1")] string arg1)
{
    string str = Request.QueryString;
    // ?arg1=001&arg2=002 ★?から後ろが全部取得できる
    
    // 各パラメータに分割して受け取れる
    var query = Request.Query;
    foreach (var key in query.Keys)
    {
        string value = query[key]; // Dictionaryっぽく扱える
        System.Console.WriteLine($"key={key}, value={value}");
    }
    // key=arg1, value=001
    // key=arg2, value=002
}

このため未指定のパラメーターも参照は可能です。

*1:「リクエストパラメーター」とか「クエリーパラメーター」、「URLクエリパラメーター」とか色々名前があります