1

I have an ActionDescriptor from which I retrieve information about an action and its controller:

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

I'm wondering if there is a better way to determine the controller's area than having to parse its namespace, which I'm currently doing like so:

// 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"

EDIT:

I should clarify that I'm not in the context of a view or controller and am trying to determine the area only given its Type information and such.

4

3 回答 3

2

ASP.NET MVC doesn't keep the AreaRegistration objects around, but AreaRegistration is how ASP.NET determines which Area a Controller belongs to.

You can just enumerate AreaRegistration types on your own within the relevant assemblies, then determine if the AreaRegistration's namespace is a prefix of the Controller's namespace. Once resolved, an AreaRegistration instance has the Area name as a property.

Rather than using reflection, you could include this in your AreaRegistration implementations themselves by providing a base class that implements RegisterArea and maintains a Namespace=>Area map.

于 2014-01-09T17:34:57.043 回答
2

Here's what I've scrambled together to get this working for every controller:

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

This fetches all the AreaRegistration types from the Web project assembly and matches the namespace of your controller to the namespace of the area. I.e. When you have a controller of type My.WebProject.Areas.Admin.UserController the system will return the Admin area based on the match of namespace My.WebProject.Areas.Admin.

于 2015-06-17T06:49:43.380 回答
0

From a view:

ViewContext.RouteData.DataTokens["area"]

From a controller:

ControllerContext.RouteData.DataTokens["area"]
于 2013-08-20T16:17:54.380 回答