如何通过命名空间限制 Asp.net Web API / Owin 发现控制器?

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

在同一个项目中,我有两个类似的启动 类 像这样:

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

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

            appBuilder.UseWebApi(config);
        }
    }
}

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

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

            appBuilder.UseWebApi(config);
        }
    }
}

我还有几个控制器,有些在命名空间 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
        }
    }
}

... 和其他在命名空间 X.B...:[=​​16=]

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
        }
    }
}

...所有控制器都在同一个组件中。

目前,所有控制器都会自动注册到 API。 我想通过命名空间限制控制器发现(即 AStartup 从 X.A...注册所有控制器,而 BStartup 从 X.B...注册所有控制器)

有没有办法用 MapHttpAttributeRoutes 做到这一点?

我也会对另一种不使用属性路由的方法感到满意(即,如果您有一种方法,我必须以编程方式显式注册每个控制器,那对我来说效果很好)。

我不知道如何使用属性路由来做到这一点。但是如果你想使用普通路由,你可以实现自定义 IAssembliesResolver(默认扫描当前应用程序域中的所有程序集以查找控制器)。

public class CustomAssemblyResolver : IAssembliesResolver
{
    private readonly Assembly[] _assemblies;

    public CustomAssemblyResolver(params Assembly[] assemblies)
    {
        _assemblies = assemblies;
    }

    public ICollection<Assembly> GetAssemblies()
    {
        return _assemblies;
    }
}

例如,在您的 AStartup 中,您可以这样使用:

public class AStartup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        HttpConfiguration config = new HttpConfiguration();

        config.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver(typeof(Controller1).Assembly));

        config.EnsureInitialized();

        appBuilder.UseWebApi(config);
    }
}

根据 peco 的回答,我在此处找到了 WEB API 服务的完整列表: http://www.asp.net/web-api/overview/advanced/configuring-aspnet-web-api

答案是实现自定义 IHttpControllerTypeResolver,在 http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection.

中有简要描述

我也在http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/

找到了很多灵感

如果这对其他人有用,这是我使用的 IHttpControllerTypeResolver:

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);
        }
    }
}

我对 BControllerTypeResolver 也做了同样的事情。

我确实像这样替换了 AStartup 中的默认服务:

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

我还必须确保我所有的控制器都派生自 ABaseController(分别是 BBaseController)。

Ramsey 基于 peco 结构的回答对我有用。

就我而言,我有一个托管 MVC/api 项目,其中包含多个 OWIN app.map'd class 库 web.api 项目。我觉得标准

config.MapHttpAttributeRoutes();

导致试图在不同的 api 项目之间注册的路由发生冲突。现在每个 OWIN api 和托管应用程序的 api 在它们继承自的命名空间中都有自己的 BaseApiController。每个 BaseApiController 都有 Ramsey 的 ControllerTypeResolver。 OWIN 项目进行自己的 WebApiConfig 设置,但现在属性路由注册如下所示:

    apiConfig.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerTypeResolver), new Core.Api.Controllers.RestrictedControllerTypeResolver());
apiConfig.MapHttpAttributeRoutes();

我对此进行了测试,现在当每个项目执行 MapHttpAttributeRoutes 时,它只会为自己项目中的控制器映射路由。

谢谢大家!