Obter o nome da área atual no modo de exibição ou controlador

126

Como você obtém o nome da área atual na visualização ou no controlador?

Existe algo parecido ViewContext.RouteData.Values["controller"]com áreas?

user202448
fonte

Respostas:

217

A partir do MVC2, você pode usar ViewContext.RouteData.DataTokens["area"]

artvolk
fonte
22
Se não estiver em uma área, ViewContext.RouteData.DataTokens ["area"] == null.
User202448
23
... e no MVC5 :)
Stefan
4
Lol .. a piada é sobre você @Dante ... bem para ser justo é chamado ASP.NET Core 1.0em vez de MVC6.. :-)
Rosdi Kasim
Para sua informação, descobri o que havia de errado com o meu POST do ajax não estava funcionando ... verifique se os pedidos de ajax estão com a área na URL ... eles ainda podem encontrar !!! a visualização, mas eles não manterão a área ... se o URL estiver ausente na área quando a solicitação for feita.
precisa saber é o seguinte
43
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
Slava
fonte
3
Essa é a melhor maneira universal de obter as informações da área, se você não estiver em uma visualização ou controlador. Obrigado por postar isso!
bdrelling
19

Você pode obtê-lo do controlador usando:

ControllerContext.RouteData.DataTokens["area"]
Matt Penner
fonte
@ user202338 As áreas foram introduzidas no MVC2, então eu suspeitaria, mas não tenho certeza se elas mudaram a maneira como preenchem a coleção DataTokens. Eu vejo posts como este: link que fala sobre usá-lo no MVC2.
Matt Penner #
10

No ASP.NET Core 1.0, o valor é encontrado em

ViewContext.RouteData.Values ​​["area"];

zerox981
fonte
Você tem certeza? Tanto quanto me lembro, funcionou quando executamos nosso aplicativo no ASP.NET Core 2.0 e ainda está trabalhando agora no ASP.NET Core 2.1 (testado momentos atrás).
Zerox981 30/10
Você está certo, não está funcionando apenas para páginas de barbear (não há ViewContext - pageModel.RouteData.Values.TryGetValue("area", out object area)deve ser usado em vez)
Roman Pokrovskij
9

Acabei de escrever uma entrada de log sobre isso , você pode visitar isso para obter mais detalhes, mas minha resposta foi criar um método de extensão, mostrado abaixo.

O ponto principal foi que você extraiu a Área MVC do .DataTokens e o controlador / ação dos .Values ​​do 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;
    }

Então você pode implementá-lo como abaixo:

<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
fonte
Por alguma razão, não consigo encontrar o areatoken no, Valuesmas precisava procurar no DataTokens... não faço ideia do porquê.
Syska
8

Eu criei um método de extensão para RouteDataque retorne o nome da área atual.

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

    return null;
}

Uma vez que RouteDataestá disponível em ambos ControllerContexte ViewContextpode ser acessado em seu controlador e visualizações.

Também é muito fácil testar:

[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();
    }
}

Não há necessidade de verificar se RouteData.DataTokensé nulo, pois isso sempre é inicializado internamente.

Ben Foster
fonte
3

O MVC Futures possui um método AreaHelpers.GetAreaName (). No entanto, tenha cuidado se você estiver usando esse método. Usar a área atual para tomar decisões de tempo de execução sobre seu aplicativo pode levar a códigos difíceis de depurar ou inseguros.

Levi
fonte
1
Existe um método como esse para controladores? Eu odeio usar literais de seqüência de caracteres em uma coleção.
Erick T
para uso do controlador this.GetName()e para o atual uso MétodoMethodBase.GetCurrentMethod().Name
Nerdroid
3

Sei que isso é antigo, mas também, quando em um filtro como o ActionFilter, o contexto não fornece facilmente as informações da área.

Pode ser encontrado no seguinte código:

var routeData = filterContext.RequestContext.RouteData;

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

Portanto, o filterContext está sendo transmitido na substituição e o RouteData correto é encontrado no RequestContext. Há um RoutData no nível Base, mas os DataTokens NÃO possuem a área em seu dicionário.

gcoleman0828
fonte
2

Para obter o nome da área na exibição, no ASP.NET Core MVC 2.1:

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

Obtenha o nome da área no modo de exibição (.NET Core 2.2):

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

Eu sei que esta é uma postagem muito antiga, mas podemos usar a propriedade Values ​​exatamente da mesma maneira que os DataTokens

Url.RequestContext.RouteData.Values ​​["action"] funcionou para mim.

João Nunes da Silva
fonte
0

Não sei por que, mas a resposta aceita não está funcionando. Ele retorna nulo com, por exemplo (talvez sobre mvc, eu uso .net core)

http: // localhost: 5000 / Admin / CustomerGroup

Eu sempre depuro a variável e busco dados nela.

Tente isso. Funciona para mim

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

Exemplo lógico detalhado

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