ASP.NET Web APIのオプションのクエリ文字列パラメーター


212

次のWebAPIメソッドを実装する必要があります。

/api/books?author=XXX&title=XXX&isbn=XXX&somethingelse=XXX&date=XXX

クエリ文字列パラメーターはすべてnullにすることができます。つまり、呼び出し元は0から5つのパラメーターすべてを指定できます。

MVC4ベータ私は、次の操作を実行するために使用しました:

public class BooksController : ApiController
{
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks(string author, string title, string isbn, string somethingelse, DateTime? date) 
    {
        // ...
    }
}

MVC4 RCは、このように動作しなくなりました。5つ未満のパラメーターを指定すると、404格言で応答します。

リクエストに一致するコントローラ「Books」でアクションが見つかりませんでした。

URLルーティングでオプションのパラメーターを指定せずに、以前のように動作させるための正しいメソッドシグネチャは何ですか?


[httpget]を実行します。
user960567 2012

2
すべてのパラメーターを設定すると、メソッドが呼び出されます。さらにGet、それはHTTP GETメソッドで自動的にバインドされるので始まります
frapontillo

これが、web apiルーティングの仕組みです。asp.net/ web
routing

4
はい。私はそれがどのように機能するかを知っています。この特定の状況では動作しません。
frapontillo 2012

これはどのようにコンパイルされましたか?string?は有効なタイプではありません。string参照型であるため、null許容型として宣言することはできません。
EkoostikMartin 2014

回答:


307

この問題は、MVC4の通常のリリースで修正されています。今あなたはできる:

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

そして、すべてが箱から出して動作します。


ここでnullをデフォルトとして使用できますか?たとえば、string author = null?
Boris Zinchenko

2
はい、定数式nullと見なされるため、有効なデフォルト値です。
JDawg 2016年

ここで述べたように、オプションのパラメーターについてもデフォルト値に言及する必要があるのはなぜでしょうか。C#のすべての型には常にデフォルト値があるため、ルーティングランタイムはURIから受け取っていない場合、その型のデフォルト値を受け取る可能性があります。これの背後にある技術的な理由は何ですか?これはモデルバインダーと関係があると思います。
2017

@RBTルートを一致させるため
James Westgate

私は日付パラメーターを使用していて、それらをnullableに設定しただけでは機能しませんでした。だから私はそれをnullableに設定し、デフォルト値としてnullを設定し、それに応じてサーバー側の検証を使用してエラーメッセージを返す必要があります。出来た。
Atta H.

85

vijayが提案するように、複数のパラメータを単一のモデルとして渡すことが可能です。これは、FromUriパラメータ属性を使用する場合のGETで機能します。これは、クエリパラメータからモデルを埋めるようにWebAPIに指示します。

その結果、パラメーターが1つだけの、よりクリーンなコントローラーアクションが得られます。詳細については、http//www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-apiを参照してください。

public class BooksController : ApiController
  {
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks([FromUri]BookQuery query)
    {
      // ...
    }
  }

  public class BookQuery
  {
    public string Author { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
    public string SomethingElse { get; set; }
    public DateTime? Date { get; set; }
  }

プロパティが競合しない限り、複数のパラメーターもサポートします。

// GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
public string GetFindBooks([FromUri]BookQuery query, [FromUri]Paging paging)
{
  // ...
}

public class Paging
{
  public string Sort { get; set; }
  public int Skip { get; set; }
  public int Take { get; set; }
}

更新
値がオプションであることを確認するには、モデルプロパティに参照型またはnull許容値(例:int?)を使用してください。


4
はい、ただし[FromUri]デコレーターだけではオプションのパラメーターをサポートしていないようです。
John Meyer、

6
@JohnMeyer [FromUri]を使用して正解です。元の質問に直接回答しません。基本的には、これらのモデルにUriからの値を入力するというものです。モデルプロパティは、オプションであることをサポートするために、null可能または参照タイプである必要があります。追加情報を追加しました。
Andrew C

@AndrewC-値がオプションであることを確認するためにnullableを使用する必要がある場合/理由について詳しく説明してください。値をnull可能にせず(たとえば、property int Skip)、そのプロパティのクエリパラメータが指定されていない場合でも、APIコントローラメソッドはリクエストを正常に照合し、のSkip値はそのタイプのデフォルト値になります。または、この場合は0
クラーク

2
@Clark-null許容型を使用しないと、ユーザーが値を指定せず、初期化されていない型の値(intの場合は0)を取得したかどうか、またはユーザーが0を指定したかどうかを知ることができません。したがって、コントローラーアクションでデフォルトを安全に適用できます。上記の例のTakeを見て、Takeに対して0を受け取った場合のアクションはどうすればよいでしょうか。ユーザーは0レコードをリクエストするつもりだったのか、それとも指定しなかったので、すべてのレコードを取得する必要があります。一般に、値のタイプ(int、boolなど)をオプションにする場合は、nullにすることができます。
アンドリューC

70

以下のようにすべてのパラメータに初期デフォルト値を使用します

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

1
これは正しい手順ですが、1つDateTimeはNULL可能ではないということです。DateTime?代わりに既に使用しようとしましたが、HTTPリクエストで一部のパラメータのみを設定した場合、MVCはリクエストを指定されたメソッドにマップしません。
frapontillo 2012

日付を文字列として渡し、DateTime.Parse()関数を使用してコントローラー関数内で解析できます。
ムハンマドアミン

1
@MuhammadAmin DateTimenull許容データ型ではありません。nullタイプのパラメータに値を割り当てることができないため、コードをコンパイルしないでくださいDateTime。おそらく、これをに変更するDateTime?か、のようなデフォルトに別の値を使用する必要がありますDateTime.Now
Ivaylo Slavov 2014

1
@IvayloSlavov DateTime.Nowはコンパイル時定数ではないため、デフォルトのパラメーターとして割り当てることはできません。
GiriB 2018年

@GiriB、あなたは本当に正しい。Datetime.Nowデフォルトのパラメータ初期化では使用できません。修正しました。
Ivaylo Slavov

1

複数のパラメーターを渡す場合は、複数のパラメーターを渡す代わりにモデルを作成できます。

パラメータを渡したくない場合はスキップすることもでき、コードはきれいに見えます。


1
これは、リクエスト本文のPOSTパラメータにのみ当てはまります。URLのパラメータは、引数として個別に参照できます。
Nathan

1

' optional'として宣言されていないパラメーターにはデフォルト値を指定できません

 Function GetFindBooks(id As Integer, ByVal pid As Integer, Optional sort As String = "DESC", Optional limit As Integer = 99)

あなたの WebApiConfig

 config.Routes.MapHttpRoute( _
          name:="books", _
          routeTemplate:="api/{controller}/{action}/{id}/{pid}/{sort}/{limit}", _
          defaults:=New With {.id = RouteParameter.Optional, .pid = RouteParameter.Optional, .sort = UrlParameter.Optional, .limit = UrlParameter.Optional} _
      )

8
実際にできます。VB.NETではなくC#を使用しています。
フラポンティージョ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.