URLにアクションが指定されていない場合、アクション名としてHTTP動詞を使用するWebAPIの組み込みのデフォルトロジックがあるようです。たとえば、次のルートがあります。
config.Routes.MapHttpRoute(
name: "DefaultApiController",
routeTemplate: "api/{controller}"
);
そして、これが私の行動です:
public IEnumerable<Conference> Get()
{
...
}
[ActionName("current")]
public IEnumerable<Conference> GetCurrent()
{
...
}
GET動詞を使用して〜/ Conferencesに移動すると、「Get()」アクションが表示されます。POST動詞を使用する場合は、「Post([FromBody] Conferencevalue)」アクション...などに移動します。〜/ Conferences / GetCurrentに移動しようとすると([ActionName( "current")]が一番上にある場合でも)、競合が発生します。
リクエストに一致する複数のアクションが見つかりました:System.Collections.Generic.IEnumerable
1[MyApp.Models.Conference] Get() on type MyApp.Api.ConferencesController System.Collections.Generic.IEnumerable
1 [MyApp.Models.Conference] GetCurrent()on type MyApp.Api.ConferencesController
これは、フレームワークがデフォルトのアクションを決定するためにEqualではなくStartsWithを使用していることを意味します。また、動詞をアクションに一致させるときにActionName属性を無視します。
私の質問は、StartsWithロジックを使用する代わりに、フレームワークのデフォルトのアクションを動詞に正確に一致させるにはどうすればよいですか?GET動詞は、Get()、GetCurrent()GetPast()などではなく、Get()アクションにのみ一致する必要があります(特に、ActionName属性を無視している場合)。
編集 簡単にするために、上記のルートの1つだけを示しました。まだドラフト中のすべてのルートを表示すると役立つと思います。独自のカスタムアクションを追加する余地を残しながら、完全に機能するRESTAPIを取得しようとしています。
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApiControllerActionId",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: null,
constraints: new { action = @"^[a-zA-Z]+$", id = @"^\d+$" } // action must start with character
);
config.Routes.MapHttpRoute(
name: "DefaultApiControllerActionName",
routeTemplate: "api/{controller}/{action}/{name}",
defaults: null,
constraints: new { action = @"^[a-zA-Z]+$", name = @"^[a-zA-Z]+$" } // action and name must start with character
);
config.Routes.MapHttpRoute(
name: "DefaultApiControllerId",
routeTemplate: "api/{controller}/{id}",
defaults: null,
constraints: new { id = @"^\d+$" } // id must be all digits
);
config.Routes.MapHttpRoute(
name: "DefaultApiControllerAction",
routeTemplate: "api/{controller}/{action}",
defaults: null,
constraints: new { action = @"^[a-zA-Z]+$" } // action must start with character
);
config.Routes.MapHttpRoute(
name: "DefaultApiController",
routeTemplate: "api/{controller}"
);
更新 HTTP動詞の制約を追加すると、次のようになります。
config.Routes.MapHttpRoute(
name: "DefaultApiControllerGet",
routeTemplate: "api/{controller}",
defaults: new { action = "Get" },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
);
config.Routes.MapHttpRoute(
name: "DefaultApiControllerPost",
routeTemplate: "api/{controller}",
defaults: new { action = "Post" },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
);
config.Routes.MapHttpRoute(
name: "DefaultApiControllerPut",
routeTemplate: "api/{controller}",
defaults: new { action = "Put" },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) }
);
config.Routes.MapHttpRoute(
name: "DefaultApiControllerDelete",
routeTemplate: "api/{controller}",
defaults: new { action = "Delete" },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete) }
);