web-dev-qa-db-ja.com

属性のルーティングと継承

汎用リポジトリーを使用して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」という名前のコントローラー。」 }

誰かがルーティングをベースコントローラーの属性で動作させる方法を知っていますか?

63
Jeff Treuting

属性ルートは継承できません。これは意図的な設計決定でした。私たちは正しくないと感じ、それらを継承することが理にかなっている有効なシナリオを見ませんでした。

これを使用したい場所について、より現実的なシナリオを教えてください。

[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);
    }
}
77
Kiran Challa

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

25
Dejan

とった。

[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つの注意点は、ルートアクションパラメーターはアクション名と同じでなければならないということです。私はそれを回避する方法を見つけることができませんでした。 (ルート属性を使用してルートの名前を変更することはできません)

3
parliament