Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restrict Asp.net Web API / Owin discovery of controllers by namespace?

Tags:

c#

asp.net

owin

In the same project, I have two similar startup classes like this :

namespace X.A
{
    public class AStartup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = new HttpConfiguration();

            config.MapHttpAttributeRoutes();
            config.EnsureInitialized();

            appBuilder.UseWebApi(config);
        }
    }
}

and

namespace X.B
{
    public class BStartup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = new HttpConfiguration();

            config.MapHttpAttributeRoutes();
            config.EnsureInitialized();

            appBuilder.UseWebApi(config);
        }
    }
}

I also have several controllers, some are in namespace X.A... :

namespace X.A.SomePlace
{
    [RoutePrefix("A/SomeRouting")]
    public class Controller1 : ApiController
    {
        [Route("SomeMethod")]
        [HttpPost]
        [ResponseType(typeof(SomeMethodResponse))]
        public IHttpActionResult GetParameters([FromBody] SomeMethodRequest request)
        {
            // Some code
        }
    }
}

... and others are in namespace X.B...:

namespace X.B.SomeOtherPlace
{
    [RoutePrefix("B/AnotherRouting")]
    public class Controller2 : ApiController
    {
        [Route("AnotherMethod")]
        [HttpPost]
        [ResponseType(typeof(AnotherMethodResponse))]
        public IHttpActionResult AnotherMethod([FromBody] AnotherMethodRequest request)
        {
            // Another code
        }
    }
}

...and all controllers are in the same Asssembly.

Currently, all controllers get automagically registered to both API. I would like to restrict the controller discovery by namespace (i.e. AStartup registers all controllers from X.A.... and BStartup registers all controllers from X.B...)

Is there a way to do this with MapHttpAttributeRoutes?

I would be also happy with another method that does not use attribute routes (i.e. if you have a method where I have to explicitely registers each controller programatically, that would work fine for me).

like image 859
Ramsey Avatar asked Mar 13 '23 01:03

Ramsey


1 Answers

Following on peco answer, I've found the whole list of WEB API Services here: http://www.asp.net/web-api/overview/advanced/configuring-aspnet-web-api

The answer was to implement a custom IHttpControllerTypeResolver which is succinctly described at http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection.

I also found a lot of inspiration at http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/

In case this is useful for someone else, here is the IHttpControllerTypeResolver I used:

namespace X.A
{
    public class AControllerTypeResolver : DefaultHttpControllerTypeResolver
    {
        public AControllerTypeResolver() : base(IsHttpEndpoint)
        {
        }

        private static bool IsHttpEndpoint(Type t)
        {    
            if (t == null) throw new ArgumentNullException("t");

            return t.IsClass &&
                t.IsVisible &&
                !t.IsAbstract &&
                typeof(ABaseController).IsAssignableFrom(t);
        }
    }
}

And I did the same for BControllerTypeResolver.

I did Replace the default service in AStartup like this:

config.Services.Replace(typeof(IHttpControllerTypeResolver), new AControllerTypeResolver());

I also had to make sure all my controllers are deriving from ABaseController (respectively BBaseController).

like image 187
Ramsey Avatar answered Apr 08 '23 20:04

Ramsey