【问题标题】:How to determine Controller's Area in ASP.NET MVC如何在 ASP.NET MVC 中确定控制器的区域
【发布时间】:2013-08-20 16:10:41
【问题描述】:

我有一个ActionDescriptor,我从中检索有关操作及其控制器的信息:

ActionDescriptor desc = ...;
string action = desc.ActionName;
string controller = desc.ControllerDescriptor.ControllerName;
string area = ?;

我想知道是否有比解析其命名空间更好的方法来确定控制器的区域,我目前正在这样做:

// e.g., Company.Areas.Foo.Controllers
var parts = desc.ControllerDescriptor.ControllerType.Namespace.Split('.').ToList();
var areaIndex = parts.IndexOf("Areas");
if (areaIndex > -1) area = parts[areaIndex + 1];
// area = "Foo"

编辑:

我应该澄清一下,我不在视图或控制器的上下文中,并且我试图仅根据其 Type 信息等来确定该区域。

【问题讨论】:

  • 原谅我。我不确定这是什么。但这有帮助吗? :stackoverflow.com/questions/2723689/…
  • 这段代码在何时何地执行?
  • @asymptoticFault 可以说,这段代码不在控制器内部执行。此外,我不是在尝试确定执行控制器的区域,而是在给定其类型的情况下确定某个控制器的区域。
  • 哦,我明白了,是的,这完全是一个不同的问题。

标签: c# asp.net-mvc


【解决方案1】:

ASP.NET MVC 不会保留 AreaRegistration 对象,但 AreaRegistration 是 ASP.NET 确定控制器所属区域的方式。

您可以在相关程序集中自行枚举 AreaRegistration 类型,然后确定 AreaRegistration 的命名空间是否是控制器命名空间的前缀。解析后,AreaRegistration 实例将 Area 名称作为属性。

您可以通过提供一个实现 RegisterArea 并维护 Namespace=>Area 映射的基类,将其包含在您的 AreaRegistration 实现中,而不是使用反射。

【讨论】:

    【解决方案2】:

    这是我为使每个控制器都能正常工作而拼凑起来的:

    private string findAreaForControllerType(Type controllerType)
    {
        var areaTypes = getAllAreasRegistered();
    
        foreach (var areaType in areaTypes)
        {
            if (controllerType.Namespace.StartsWith(areaType.Namespace))
            {
                var area = (AreaRegistration)Activator.CreateInstance(areaType);
                return area.AreaName;
            }
        }
        return string.Empty;
    }
    
    private IEnumerable<Type> getAllAreasRegistered()
    {
        var assembly = getWebEntryAssembly();
        var areaTypes = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(AreaRegistration)));
    
        return areaTypes;
    }
    
    static private Assembly getWebEntryAssembly()
    {
        if (System.Web.HttpContext.Current == null ||
            System.Web.HttpContext.Current.ApplicationInstance == null)
        {
            return null;
        }
    
        var type = System.Web.HttpContext.Current.ApplicationInstance.GetType();
        while (type != null && type.Namespace == "ASP")
        {
            type = type.BaseType;
        }
    
        return type == null ? null : type.Assembly;
    }
    

    这会从 Web 项目程序集中获取所有 AreaRegistration 类型,并将控制器的命名空间与区域的命名空间相匹配。 IE。当您拥有My.WebProject.Areas.Admin.UserController 类型的控制器时,系统将根据命名空间My.WebProject.Areas.Admin 的匹配返回管理区域。

    【讨论】:

      【解决方案3】:

      从一个角度来看:

      ViewContext.RouteData.DataTokens["area"]
      

      来自控制器:

      ControllerContext.RouteData.DataTokens["area"]
      

      【讨论】:

      • 从问题中可能不清楚,但这个答案是不相关的。我不是试图确定当前上下文中控制器的区域,而是任何给定控制器类型的区域。
      • 我能够从控制器获取区域,但这样做是:HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"].ToString().ToLower();跨度>
      • 对于那些对视图感兴趣的人,ViewContext.RouteData.DataTokens["area"] 在 MVC 的最新版本中似乎已成为 ViewContext.RouteData.Values["area"]。或者至少对我来说:)
      猜你喜欢
      • 1970-01-01
      • 2015-12-05
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 2013-02-13
      • 2023-03-14
      相关资源
      最近更新 更多