Obtener el nombre del área actual en la vista o el controlador

126

¿Cómo se obtiene el nombre del área actual en la vista o controlador?

¿Hay algo parecido ViewContext.RouteData.Values["controller"]a las áreas?

usuario202448
fuente

Respuestas:

217

Desde MVC2 en adelante puedes usar ViewContext.RouteData.DataTokens["area"]

artvolk
fuente
22
Si no está en un área, ViewContext.RouteData.DataTokens ["area"] == null.
user202448
23
... y en MVC5 :)
Stefan
44
Lol ... la broma está en ti @Dante ... bueno, para ser justos, se llama en ASP.NET Core 1.0lugar de MVC6... :-)
Rosdi Kasim
FYI - descubrí que lo que estaba mal con mi ajax POST no funcionaba ... por favor verifique que sus solicitudes de ajax tengan el área en la URL ... ¡aún pueden encontrarlas! la vista, pero no mantendrán el área ... si a la url le falta el área cuando se realiza la solicitud.
Seabizkit
43
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
Slava
fuente
3
Esta es la mejor forma universal de obtener la información del área, si no está dentro de una vista o controlador. ¡Gracias por publicar esto!
bdrelling
19

Puede obtenerlo del controlador usando:

ControllerContext.RouteData.DataTokens["area"]
Matt Penner
fuente
@ user202338 Las áreas se introdujeron en MVC2, por lo que sospecho que sí, pero no estoy seguro de si han cambiado la forma en que pueblan la colección DataTokens. Veo publicaciones como esta: enlaces que hablan sobre su uso en MVC2.
Matt Penner
10

En ASP.NET Core 1.0, el valor se encuentra en

ViewContext.RouteData.Values ​​["área"];

zerox981
fuente
¿Estás seguro? Hasta donde puedo recordar, funcionó cuando ejecutamos nuestra aplicación en ASP.NET Core 2.0 y todavía funciona ahora en ASP.NET Core 2.1 (probado hace unos momentos).
zerox981
Tienes razón, no solo trabajas para Razor Pages (no hay ViewContext, pageModel.RouteData.Values.TryGetValue("area", out object area)debería usarse en su lugar)
Roman Pokrovskij
9

Acabo de escribir una entrada de registro ab sobre esto , puede visitarla para obtener más detalles, pero mi respuesta fue crear un Método de extensión, que se muestra a continuación.

El factor clave fue que extrajo el Área MVC de .DataTokens y el controlador / acción de .Values ​​de RouteData.

public static MvcHtmlString TopMenuLink(this HtmlHelper htmlHelper, string linkText, string controller, string action, string area, string anchorTitle)
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
        var url = urlHelper.Action(action, controller, new { @area = area });

        var anchor = new TagBuilder("a");
        anchor.InnerHtml = HttpUtility.HtmlEncode(linkText);
        anchor.MergeAttribute("href", url);
        anchor.Attributes.Add("title", anchorTitle);

        var listItem = new TagBuilder("li");
        listItem.InnerHtml = anchor.ToString(TagRenderMode.Normal);

        if (CheckForActiveItem(htmlHelper, controller, action, area))
            listItem.GenerateId("menu_active");

        return MvcHtmlString.Create(listItem.ToString(TagRenderMode.Normal));
    }

    private static bool CheckForActiveItem(HtmlHelper htmlHelper, string controller, string action, string area)
    {
        if (!CheckIfTokenMatches(htmlHelper, area, "area"))
            return false;

        if (!CheckIfValueMatches(htmlHelper, controller, "controller"))
            return false;

        return CheckIfValueMatches(htmlHelper, action, "action");
    }

    private static bool CheckIfValueMatches(HtmlHelper htmlHelper, string item, string dataToken)
    {
        var routeData = (string)htmlHelper.ViewContext.RouteData.Values[dataToken];

        if (routeData == null) return string.IsNullOrEmpty(item);

        return routeData == item;
    }

    private static bool CheckIfTokenMatches(HtmlHelper htmlHelper, string item, string dataToken)
    {
        var routeData = (string)htmlHelper.ViewContext.RouteData.DataTokens[dataToken];

        if (dataToken == "action" && item == "Index" && string.IsNullOrEmpty(routeData))
            return true;

        if (dataToken == "controller" && item == "Home" && string.IsNullOrEmpty(routeData))
            return true;

        if (routeData == null) return string.IsNullOrEmpty(item);

        return routeData == item;
    }

Luego puede implementarlo de la siguiente manera:

<ul id="menu">
@Html.TopMenuLink("Dashboard", "Home", "Index", "", "Click here for the dashboard.")
@Html.TopMenuLink("Courses", "Home", "Index", "Courses", "List of our Courses.")
</ul>
christesene
fuente
Por alguna razón, no puedo encontrar el areatoken en el, Valuespero necesitaba buscar en el DataTokens... no tengo idea de por qué.
Syska
8

Creé un método de extensión para RouteDataque devuelva el nombre del área actual.

public static string GetAreaName(this RouteData routeData)
{
    object area;
    if (routeData.DataTokens.TryGetValue("area", out area))
    {
        return area as string;
    }

    return null;
}

Dado que RouteDataestá disponible en ambos ControllerContexty ViewContextse puede acceder en su controlador y vistas.

También es muy fácil de probar:

[TestFixture]
public class RouteDataExtensionsTests
{
    [Test]
    public void GetAreaName_should_return_area_name()
    {
        var routeData = new RouteData();
        routeData.DataTokens.Add("area", "Admin");
        routeData.GetAreaName().ShouldEqual("Admin");
    }

    [Test]
    public void GetAreaName_should_return_null_when_not_set()
    {
        var routeData = new RouteData();
        routeData.GetAreaName().ShouldBeNull();
    }
}

No es necesario verificar si RouteData.DataTokenses nulo ya que esto siempre se inicializa internamente.

Ben Foster
fuente
3

MVC Futures tiene un método AreaHelpers.GetAreaName (). Sin embargo, tenga cuidado si está utilizando este método. El uso del área actual para tomar decisiones de tiempo de ejecución sobre su aplicación podría conducir a un código difícil de depurar o inseguro.

Levi
fuente
1
¿Existe un método como ese para los controladores? Odio usar literales de cadena en una colección.
Erick T
para uso del controlador this.GetName()y para el uso del Método actualMethodBase.GetCurrentMethod().Name
Nerdroid
3

Sé que esto es antiguo, pero también, cuando está en un filtro como ActionFilter, el contexto no le proporciona fácilmente la información del área.

Se puede encontrar en el siguiente código:

var routeData = filterContext.RequestContext.RouteData;

if (routeData.DataTokens["area"] != null)
    area = routeData.DataTokens["area"].ToString();

Por lo tanto, el filterContext se pasa en la anulación y se encuentra el RouteData correcto en RequestContext. Hay un RoutData en el nivel Base, pero los DataTokens NO tienen el área en su diccionario.

gcoleman0828
fuente
2

Para obtener el nombre del área en la vista, en ASP.NET Core MVC 2.1:

@Context.GetRouteData().Values["area"]
Netstep
fuente
2

Obtener el nombre del área en Vista (.NET Core 2.2):

ViewContext?.ActionDescriptor?.RouteValues["area"]
SZL
fuente
0

Sé que esta es una publicación muy antigua, pero podemos usar la propiedad de valores exactamente de la misma manera que DataTokens

Url.RequestContext.RouteData.Values ​​["action"] funcionó para mí.

Joao Nunes da Silva
fuente
0

No sé por qué, pero la respuesta aceptada no funciona. Devuelve nulo con, por ejemplo, (tal vez sobre mvc, uso .net core)

http: // localhost: 5000 / Admin / CustomerGroup

Siempre depuro la variable y obtengo datos de ella.

Prueba esto. Esto funciona para mi

var area = ViewContext.RouteData.Values["area"]

Ejemplo lógico detallado

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
fthopkins
fuente