【问题标题】:Controller in separate assembly and routing单独装配和路由中的控制器
【发布时间】:2012-06-20 02:38:53
【问题描述】:

在同一个解决方案中,还有一个 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'。

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

【问题讨论】:

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


    【解决方案1】:

    路由上的命名空间列表只为某些命名空间提供优先级,而不是其他未列出的命名空间:

    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;
    

    【讨论】:

      【解决方案2】:

      你可以像这样从 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 的类型都将不可见。您甚至可以隐藏整个程序集。

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

      【讨论】:

      • 不幸的是,这并不是我的问题所在。我的问题是我无权访问主机应用程序,因此创建自定义控制器工厂对我不起作用。
      • @alexanderb: 不,你可以这样做,使用这个:[assembly: System.Web.PreApplicationStartMethod(typeof(MvcTools.Hooks.PreApplicationStartCode), "Start")],见这个链接:@ 987654321@ 在开始时,你这样做: System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(YOUR_ControllerFactory));您需要做的就是让主机应用程序加载您的 dll,您可以通过 web.config 条目来实现;)
      猜你喜欢
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2014-11-10
      • 2017-08-23
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多