控制器在单独的装配和布线中

时间:2012-06-18 05:55:44

标签: c# asp.net .net asp.net-mvc

在同一解决方案中,有一个ASP.NET MVC4应用程序Slick.App和类库Awesome.Mvc.Lib。 Awesome.Mvc.Lib包含一个控制器类。

public class ShinnyController : Controller
{
    [HttpGet]
    public string Index()
    {
        return "Hello, from Awesome.Mvc.Lib";
    }
}

如果我只是将Slick.App的引用添加到Awesome.Mvc.Lib,运行应用程序并将浏览器指向/shinny,我实际上会看到响应“Hello,来自Awesome.Mvc.Lib”。

这是我根本没想到的。我一直认为ASP.NET MVC尊重控制器所在的命名空间。因此,至少在我没有要求之前,来自其他命名空间的控制器都没有暴露出来。

我尝试更改默认路由注册,以使用namespaces参数。

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new [] { "Slick.App.Controllers" }
    );

尽管如此,ShinnyController路线仍然匹配'/ shinny'。

我担心这是正确的默认行为。我的问题是,如何明确说明哪些控制器被暴露并阻止默认路由匹配单独的类库中的控制器?

2 个答案:

答案 0 :(得分:31)

路由上的命名空间列表仅将 优先级 提供给其他未列出的名称空间:

new [] {"Namespace1", "Namespace2"}

没有像人们期望的那样给予Namespace1更高的优先级,但只优先于其他名称空间。

这意味着列表中的命名空间首先搜索控制器,然后,如果找不到匹配项,则使用具有该名称的其余可用控制器。

您可以通过执行以下操作来禁止使用非优先控制器:

var myRoute  = routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new [] { "Slick.App.Controllers" }
    );

myRoute.DataTokens["UseNamespaceFallback"] = false;

答案 1 :(得分:3)

您可以像这样继承DefaultControllerFactory:

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        var type = base.GetControllerType(requestContext, controllerName);

        if (type != null && IsIngored(type))
        {
            return null;
        }

        return type;
    }

    public static bool IsIngored(Type type)
    {
        return type.Assembly.GetCustomAttributes(typeof(IgnoreAssemblyAttribute), false).Any() 
            || type.GetCustomAttributes(typeof(IgnoreControllerAttribute), false).Any();
    }
}

然后对Global.asax进行一些更改

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
    }

你在这里!任何标有IgnoreControllerAttribute的类型都不可见。你甚至可以隐藏整个组件。

如果您需要一些基于配置的行为,那么进行所有必要的更改并不是一件好事;)