1. ホーム
  2. c#

[解決済み] Web API コントローラで複数の HttpPost メソッドを使用する場合

2022-07-05 20:02:07

質問

MVC4 Web API プロジェクトを使い始めていますが、複数の HttpPost メソッドを持つコントローラがあります。コントローラは以下のような感じです。

コントローラ

public class VTRoutingController : ApiController
{
    [HttpPost]
    public MyResult Route(MyRequestTemplate routingRequestTemplate)
    {
        return null;
    }

    [HttpPost]
    public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate)
    {
        return null;
    }
}

ここで MyRequestTemplate は、リクエストを通して送られてくる Json を処理する責任を負うテンプレートクラスを表します。

エラーです。

Fiddler を使って http://localhost:52370/api/VTRouting/TSPRoute または http://localhost:52370/api/VTRouting/Route というエラーが出ます。

リクエストにマッチするアクションが複数見つかりました。

上記の方法のうち1つを削除すると、正常に動作します。

グローバル.asax

でデフォルトのルーティングテーブルを変更してみました。 global.asax にあるデフォルトのルーティングテーブルを変更してみましたが、まだエラーが出ます。私はglobal.asaxでのルート定義に問題があると思います。以下は、私がglobal.asaxで行っていることです。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapHttpRoute(
        name: "MyTSPRoute",
        routeTemplate: "api/VTRouting/TSPRoute",
        defaults: new { }
    );

    routes.MapHttpRoute(
        name: "MyRoute",
        routeTemplate: "api/VTRouting/Route",
        defaults: new { action="Route" }
    );
}

FiddlerでPOSTでリクエストを行い、RequestBodyでMyRequestTemplateにjsonを渡しています。

どのように解決するのですか?

一つのコントローラで複数のアクションを持つことができます。

そのためには、以下の2つのことを行う必要があります。

  • まず、アクションを ActionName 属性で装飾します。

     [ActionName("route")]
     public class VTRoutingController : ApiController
     {
       [ActionName("route")]
       public MyResult PostRoute(MyRequestTemplate routingRequestTemplate)
       {
         return null;
       }
    
      [ActionName("tspRoute")]
      public MyResult PostTSPRoute(MyRequestTemplate routingRequestTemplate)
      {
         return null;
      }
    }
    
    
  • 次に、以下のルートを WebApiConfig ファイルに記述します。

    // Controller Only
    // To handle routes like `/api/VTRouting`
    config.Routes.MapHttpRoute(
        name: "ControllerOnly",
        routeTemplate: "api/{controller}"               
    );
    
    
    // Controller with ID
    // To handle routes like `/api/VTRouting/1`
    config.Routes.MapHttpRoute(
        name: "ControllerAndId",
        routeTemplate: "api/{controller}/{id}",
        defaults: null,
        constraints: new { id = @"^\d+$" } // Only integers 
    );
    
    // Controllers with Actions
    // To handle routes like `/api/VTRouting/route`
    config.Routes.MapHttpRoute(
        name: "ControllerAndAction",
        routeTemplate: "api/{controller}/{action}"
    );