9

テストモデルを用意しましょう。

public class TestRequestModel
{
    public string Text { get; set; }
    public int Number { get; set; }
}

このサービスで次の要求を受け入れることができるようにしたいと考えています。

  • GET /test?Number=1234&Text=MyText
  • POST /test with header: Content-Type: application/x-www-form-urlencoded and body: Number=1234&Text=MyText
  • POST /test with header: Content-Type: application/json and body: {"Text":"Provided!","Number":9876}

ルートは次のように構成されます。

_config.Routes.MapHttpRoute(
   "DefaultPost", "/{controller}/{action}",
   new { action = "Post" }, 
   new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) });

_config.Routes.MapHttpRoute(
   "The rest", "/{controller}/{action}",
   defaults: new { action = "Get" });

私のコントローラーは次のようになります。

public class TestController : ApiController
{
    [HttpGet]
    public TestResponseModel Get([FromUri] TestRequestModel model)
    {
       return Do(model);
    }

    [HttpPost]
    public TestResponseModel Post([FromBody] TestRequestModel model)
    {
       return Do(model);
    }
    (...)

これは定型コードの許容量のように思えますが、可能であれば避けたいと思います。

余分なルートを持つことも理想的ではありません。私は MVC/WebAPI ルートを恐れており、悪だと信じています。

2 つのメソッドやDefaultPostルートを避ける方法はありますか?

4

1 に答える 1

8

あなたが求めているのは、ASP.NET Web API では一般的ではありません。ASP.NET MVC では、最初の GET とその後のポスト バック (POST) を処理する同じアクション メソッドを持つのが一般的です。ASP.NET Web API は HTTP サービスの構築を目的としており、GET はシステム内で何も変更せずにリソースを取得するために使用されますが、POST は Matthew が指摘したように新しいリソースを作成するために使用されます。

いずれにせよ、これを実現するために Web API に 1 つのアクション メソッドを用意することは不可能ではありません。ただし、同じアクション メソッドで GET と POST を処理するだけでなく、モデル バインディングとフォーマッタ バインディングも実行する必要があります。モデル バインディング (MVC に類似) はリクエスト URI、クエリ文字列などをパラメーターにバインドし、フォーマッター バインディング (Web API に固有) は本文のコンテンツをパラメーターにバインドします。デフォルトでは、単純型は URI からバインドされ、クエリ文字列はバインドされ、複合型は本文からバインドされます。したがって、次のパラメーターを持つアクション メソッドがある場合、string text, int number, TestRequestModel model、URIまたは本文からWeb APIをバインドできます。この場合、空でないものを確認してそれを使用する必要があります。しかし、残念ながら、そのようなソリューションはハックのように見えます。または、URI/クエリ文字列と本文の両方から同じ複合型を設定する場合は、リクエスト パーツをチェックし、それに応じてパラメーターを設定する独自のパラメーター バインダーを作成する必要があります。

また、ルート マッピングを 2 つ持つ必要はありません。このようなデフォルトのもので十分です。

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
于 2013-08-05T10:53:34.057 に答える