38

在同一个解决方案中,还有一个 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,我实际上会看到响应“你好,来自 Awesome.Mvc.Lib”。

这是我完全没想到的。我一直认为 ASP.NET MVC 尊重放置控制器的命名空间。因此,来自另一个命名空间的控制器没有暴露,至少在我没有要求之前。

我试图更改默认路由注册,以使用命名空间参数。

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

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

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

4

2 回答 2

32

路由上的命名空间列表仅将某些命名空间优先于其他未列出的命名空间:

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;
于 2012-06-18T08:32:22.473 回答
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 的类型都将不可见。您甚至可以隐藏整个程序集。

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

于 2012-07-25T16:41:06.463 回答