汎用リポジトリーを使用してAPIコントローラーに基本的なCRUDメソッドを提供するベースコントローラーを使用して、新しいコントローラーごとに同じ基本コードを複製する必要がないように考えています。しかし、ベースコントローラーにあるときにルーティング属性が認識されるという問題が発生しています。私が抱えている問題を正確に示すために、非常に単純なWebAPIコントローラーを作成しました。
メインコントローラーにGet
メソッドがあり、ApiController
から直接継承する場合、問題はなく、期待どおりに機能します。
[RoutePrefix("admin/test")]
public class TestController : ApiController
{
[Route("{id:int:min(1)}")]
public string Get(int id)
{
return "Success";
}
}
Get
メソッドをベースコントローラーに移動すると、404ページのコンテンツが返されます。
[RoutePrefix("admin/test")]
public class TestController : TestBaseController
{
}
public class TestBaseController : ApiController
{
[Route("{id:int:min(1)}")]
public string Get(int id)
{
return "Success";
}
}
さらに興味深いメモ:
GET
/Test/1
でアクションにアクセスできます。そのため、デフォルトルートに基づいてそれを見つけています。
POST
/admin/test
にアクセスしようとすると、次のJSONが返されます
{"メッセージ": "リクエストURI ' http://test.com/admin/test '。に一致するHTTPリソースが見つかりませんでした。"、 "MessageDetail": "一致するタイプが見つかりませんでした「admin」という名前のコントローラー。」 }
誰かがルーティングをベースコントローラーの属性で動作させる方法を知っていますか?
属性ルートは継承できません。これは意図的な設計決定でした。私たちは正しくないと感じ、それらを継承することが理にかなっている有効なシナリオを見ませんでした。
これを使用したい場所について、より現実的なシナリオを教えてください。
[Update(3/24/2014)]
MVC Web APIの今後の5.2リリースでは、System.Web.Http.Routing.IDirectRouteProvider
ここで探している継承シナリオを有効にすることができます。最新のナイトビルドを使用して自分でこれを試すことができます(ナイトビルドの使用方法に関するドキュメントは here )
[Update(7/31/2014)]
Web APIでこれを行う方法の例2.2
リリース:
config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
//---------
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
// inherit route attributes decorated on base class controller's actions
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
(inherit: true);
}
}
Web API 2.2を使用すると、次のことができます。
public class BaseController : ApiController
{
[Route("{id:int}")]
public string Get(int id)
{
return "Success:" + id;
}
}
[RoutePrefix("api/values")]
public class ValuesController : BaseController
{
}
config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
(inherit: true);
}
}
ここに概説されているように: http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22
とった。
[Route("api/baseuploader/{action}")]
public abstract class BaseUploaderController : ApiController
{
[HttpGet]
public string UploadFile()
{
return "UploadFile";
}
}
[Route("api/values/{action}")]
public class ValuesController : BaseUploaderController
{
[HttpGet]
public string Get(int id)
{
return "value";
}
}
ここでの1つの注意点は、ルートアクションパラメーターはアクション名と同じでなければならないということです。私はそれを回避する方法を見つけることができませんでした。 (ルート属性を使用してルートの名前を変更することはできません)