Obtenir le nom de la zone actuelle dans la vue ou le contrôleur


126

Comment obtenez-vous le nom de la zone actuelle dans la vue ou le contrôleur?

Y a-t-il quelque chose comme ViewContext.RouteData.Values["controller"]pour les zones?

Réponses:


217

À partir de MVC2, vous pouvez utiliser ViewContext.RouteData.DataTokens["area"]


22
Si ce n'est pas dans une zone, ViewContext.RouteData.DataTokens ["area"] == null.
user202448

23
... et dans MVC5 :)
Stefan

4
Lol .. la blague est sur toi @Dante ... eh bien, pour être honnête, elle s'appelle à la ASP.NET Core 1.0place de MVC6.. :-)
Rosdi Kasim

FYI - compris ce qui n'allait pas avec mon ajax POST ne fonctionnait pas ... s'il vous plaît vérifier vos demandes ajax ont la zone dans l'URL ... ils peuvent toujours trouver !!! la vue, mais ils ne maintiendront pas la zone ... si l'URL manque la zone lorsque la demande est faite.
Seabizkit

43
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]

3
C'est le meilleur moyen universel d'obtenir les informations de la zone, si vous n'êtes pas dans une vue ou un contrôleur. Merci d'avoir publié ceci!
bdrelling

19

Vous pouvez l'obtenir à partir du contrôleur en utilisant:

ControllerContext.RouteData.DataTokens["area"]

@ user202338 Des zones ont été introduites dans MVC2, donc je suppose que oui, mais je ne suis pas sûr qu'elles aient changé la façon dont elles peuplent la collection DataTokens. Je vois des articles comme celui-ci: un lien qui parle de son utilisation dans MVC2.
Matt Penner

10

Dans ASP.NET Core 1.0, la valeur se trouve dans

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


Êtes-vous sûr? Pour autant que je me souvienne, cela a fonctionné lorsque nous avons exécuté notre application sur ASP.NET Core 2.0 et fonctionne toujours maintenant dans ASP.NET Core 2.1 (testé il y a quelques instants).
zerox981

Vous avez raison, ne travaillez pas uniquement pour Razor Pages (il n'y a pas de ViewContext - pageModel.RouteData.Values.TryGetValue("area", out object area)devrait être utilisé à la place)
Roman Pokrovskij

9

Je viens d'écrire une entrée de journal ab à ce sujet , vous pouvez le visiter pour plus de détails, mais ma réponse a été de créer une méthode d'extension, illustrée ci-dessous.

Le déclencheur clé était que vous extrayiez la zone MVC des .DataTokens et le contrôleur / l'action des .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;
    }

Ensuite, vous pouvez l'implémenter comme ci-dessous:

<ul id="menu">
@Html.TopMenuLink("Dashboard", "Home", "Index", "", "Click here for the dashboard.")
@Html.TopMenuLink("Courses", "Home", "Index", "Courses", "List of our Courses.")
</ul>

Pour une raison quelconque, je ne trouve pas le areajeton dans le Valuesmais je devais regarder dans le DataTokens... aucune idée pourquoi.
Syska le

8

J'ai créé une méthode d'extension pour RouteDataqui renvoie le nom de la zone actuelle.

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

    return null;
}

Depuis RouteDataest disponible sur les deux ControllerContextet ViewContextil est accessible dans votre contrôleur et vos vues.

Il est également très facile de tester:

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

Il n'est pas nécessaire de vérifier si RouteData.DataTokensest nul car il est toujours initialisé en interne.


3

MVC Futures a une méthode AreaHelpers.GetAreaName (). Cependant, soyez prudent si vous utilisez cette méthode. L'utilisation de la zone actuelle pour prendre des décisions d'exécution concernant votre application peut entraîner un code difficile à déboguer ou non sécurisé.


1
Existe-t-il une méthode comme celle-là pour les contrôleurs? Je déteste utiliser des chaînes littérales dans une collection.
Erick T

pour l'utilisation du contrôleur this.GetName()et pour l'utilisation actuelle de la méthodeMethodBase.GetCurrentMethod().Name
Nerdroid

3

Je sais que c'est vieux, mais aussi, quand dans un filtre comme ActionFilter, le contexte ne vous fournit pas facilement les informations de zone.

Il peut être trouvé dans le code suivant:

var routeData = filterContext.RequestContext.RouteData;

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

Ainsi, le filterContext est transmis lors du remplacement et le RouteData correct se trouve sous RequestContext. Il y a un RoutData au niveau de base, mais les DataTokens n'ont PAS la zone dans leur dictionnaire.


2

Pour obtenir le nom de la zone dans la vue, dans ASP.NET Core MVC 2.1:

@Context.GetRouteData().Values["area"]

2

Obtenez le nom de la zone dans View (.NET Core 2.2):

ViewContext?.ActionDescriptor?.RouteValues["area"]

0

Je sais que c'est un article très très ancien, mais nous pouvons utiliser la propriété Values ​​exactement de la même manière que les DataTokens

Url.RequestContext.RouteData.Values ​​["action"] a fonctionné pour moi.


0

Je ne sais pas pourquoi mais la réponse acceptée ne fonctionne pas. Il renvoie null avec par exemple (peut-être à propos de mvc, j'utilise .net core)

http: // localhost: 5000 / Admin / CustomerGroup

Je débogue toujours la variable et j'y extrait des données.

Essaye ça. Ça marche pour moi

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

Exemple logique détaillé

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.