読者です 読者をやめる 読者になる 読者になる

ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

ASP.NET Web API のコントローラーをグループ化する

ASP.NET Web API を利用した大規模なアプリケーションでは、コントローラーを複数のグループに分割し、それぞれのグループで個別に開発したくなります。例えば、ユーザー向け(test1)と管理者向け(test2)の Web API を分けるケースなどがあります。

  • GET api/test1/
  • GET api/admin/test2/

そこで、ASP.NET Web API のコントローラーをグループ化する方法を考えてみました。

ASP.NET MVC の Area を利用した場合

ASP.NET MVC には、区分(Area)というコントローラーをグループ化する機能があります。

まず、ユーザー向けの Web API を実装します。

#Test1Controller.cs
namespace WebApplication1.Controllers
{
    public class Test1Controller : ApiController
    {
        public string Get()
        {
            return "Test1Controller";
        }
    }
}
#WebApiConfig.cs
namespace WebApplication1
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
 
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

次に、管理者向けの Web API を区分(Area)に実装します。

#Test2Controller.cs
namespace WebApplication1.Areas.Admin.Controllers
{
    public class Test2Controller : ApiController
    {
        public string Get()
        {
            return "Admin.Test1Controller";
        }
    }
}
#AdminAreaRegistration.cs
namespace WebApplication1.Areas.Admin
{
    public class AdminAreaRegistration : AreaRegistration
    {
        public override string AreaName { get { return "Admin"; } }
 
        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.Routes.MapHttpRoute(
                name: "Admin_DefaultApi",
                routeTemplate: "api/Admin/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

このように実装すると、ユーザー向け(test1)と管理者向け(test2)のコントローラーを定義できますが、2つの課題があります。1つめは、ユーザー向けのコントローラー(test1)を管理者向けのURLからもリクエストできてしまうことです。(その逆も)

  • GET api/test2/
  • GET api/admin/test1/

2つめは、異なる名前空間の同名のコントローラーを定義することができないことです。

ASP.NET Web API の Attribute Routing を利用した場合

ASP.NET Web API 2.0 の新機能に、Attribute Routing があります。

まず、ユーザー向けの Web API を実装します。

#Test1Controller.cs
namespace WebApplication1.Controllers
{
    [Route("api/test1")]
    public class Test1Controller : ApiController
    {
        public string Get()
        {
            return "Test1Controller";
        }
    }
}

次に、管理者向けの Web API を実装します。

#Test2Controller.cs
namespace WebApplication1.Admin.Controllers
{
    [Route("api/admin/test2")]
    public class Test2Controller : ApiController
    {
        public string Get()
        {
            return "Admin.Test1Controller";
        }
    }
}

このように実装すると、ユーザー向け(test1)と管理者向け(test2)のコントローラーを定義できます。ユーザー向けのコントローラー(test1)は、管理者向けのURLからはリクエストできません。しかし、異なる名前空間の同名のコントローラーを定義することができない課題は残ります。

まとめ

ASP.NET MVC のコントローラーであれば、区分(Area)を利用することで、それぞれのグループで個別に開発できます。他のグループのURLからリクエストされることはないですし、異なる名前空間の同名のコントローラーも定義できます。一方、ASP.NET Web API では、区分(Area)が上手く機能しないので、Attribute Routing を使うことになりそうです。ただし、同名のコントローラーが定義されないように、命名規則を設けるなどの工夫は行ったほうがよいかと思います。