Uzyskaj bieżącą nazwę obszaru w widoku lub kontrolerze

126

Jak uzyskać bieżącą nazwę obszaru w widoku lub kontrolerze?

Czy jest coś podobnego ViewContext.RouteData.Values["controller"]do obszarów?

user202448
źródło

Odpowiedzi:

217

Od MVC2 możesz używać ViewContext.RouteData.DataTokens["area"]

artvolk
źródło
22
Jeśli nie w jakimś obszarze, ViewContext.RouteData.DataTokens ["area"] == null.
user202448
23
... oraz w MVC5 :)
Stefan
4
Lol .. żart jest z ciebie @Dante ... cóż, żeby być uczciwym, nazywa się go ASP.NET Core 1.0zamiast MVC6.. :-)
Rosdi Kasim
Do Twojej wiadomości - dowiedziałem się, co jest nie tak z moim postem Ajax nie działa ... proszę sprawdzić, czy żądania AJAX mają obszar w adresie URL ... nadal mogą znaleźć !!! widok, ale nie utrzymają obszaru ... jeśli w adresie URL brakuje obszaru w momencie żądania.
Seabizkit
43
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
Slava
źródło
3
To najlepszy, uniwersalny sposób uzyskiwania informacji o obszarze, jeśli nie jesteś w widoku lub kontrolerze. Dzięki za opublikowanie tego!
bdrelling
19

Możesz go pobrać z kontrolera za pomocą:

ControllerContext.RouteData.DataTokens["area"]
Matt Penner
źródło
@ user202338 Obszary zostały wprowadzone w MVC2, więc podejrzewam, że tak, ale nie jestem pewien, czy zmieniły sposób, w jaki zapełniają kolekcję DataTokens. Widzę posty takie jak ten: link, który mówi o używaniu go w MVC2.
Matt Penner
10

W ASP.NET Core 1.0 wartość znajduje się w

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

zerox981
źródło
Jesteś pewny? O ile dobrze pamiętam, zadziałało, gdy uruchomiliśmy naszą aplikację na ASP.NET Core 2.0 i nadal działa w ASP.NET Core 2.1 (testowane chwilę temu).
zerox981
Masz rację, nie pracujesz tylko dla Razor Pages (nie ma ViewContext - pageModel.RouteData.Values.TryGetValue("area", out object area)należy go zamiast tego użyć)
Roman Pokrovskij
9

Właśnie napisałem wpis w dzienniku ab na ten temat , możesz go odwiedzić, aby uzyskać więcej informacji, ale moją odpowiedzią było utworzenie metody rozszerzenia, pokazanej poniżej.

Kluczowym kicker było to, że wyciągasz obszar MVC z .DataTokens, a kontroler / akcja z .Values ​​of the 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;
    }

Następnie możesz to zaimplementować jak poniżej:

<ul id="menu">
@Html.TopMenuLink("Dashboard", "Home", "Index", "", "Click here for the dashboard.")
@Html.TopMenuLink("Courses", "Home", "Index", "Courses", "List of our Courses.")
</ul>
chrystianizm
źródło
Z jakiegoś powodu nie mogę znaleźć areatokena w, Valuesale musiałem zajrzeć do DataTokens... nie mam pojęcia dlaczego.
Syska
8

Stworzyłem metodę rozszerzenia, RouteDataktóra zwraca bieżącą nazwę obszaru.

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

    return null;
}

Ponieważ RouteDatajest dostępny na obu ControllerContexti ViewContextmożna uzyskać do niego dostęp w kontrolerze i widokach.

Bardzo łatwo jest też przetestować:

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

Nie ma potrzeby sprawdzania, czy RouteData.DataTokensjest null, ponieważ jest to zawsze inicjowane wewnętrznie.

Ben Foster
źródło
3

MVC Futures ma metodę AreaHelpers.GetAreaName (). Jednak zachowaj ostrożność, jeśli używasz tej metody. Używanie bieżącego obszaru do podejmowania decyzji dotyczących aplikacji w czasie wykonywania może prowadzić do trudnego do debugowania lub niezabezpieczonego kodu.

Levi
źródło
1
Czy istnieje taka metoda dla kontrolerów? Nienawidzę używać literałów ciągów w kolekcji.
Erick T
do użytku kontrolera this.GetName()i do bieżącego użycia metodyMethodBase.GetCurrentMethod().Name
Nerdroid
3

Wiem, że to jest stare, ale także w filtrze takim jak ActionFilter kontekst nie zapewnia łatwo informacji o obszarze.

Można go znaleźć w następującym kodzie:

var routeData = filterContext.RequestContext.RouteData;

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

Tak więc filterContext jest przekazywana w przypadku zastąpienia, a poprawne RouteData znajduje się w RequestContext. Istnieje RoutData na poziomie podstawowym, ale DataTokens NIE mają obszaru w swoim słowniku.

gcoleman0828
źródło
2

Aby uzyskać nazwę obszaru w widoku, w ASP.NET Core MVC 2.1:

@Context.GetRouteData().Values["area"]
Netstep
źródło
2

Pobierz nazwę obszaru w widoku (.NET Core 2.2):

ViewContext?.ActionDescriptor?.RouteValues["area"]
SZL
źródło
0

Wiem, że to bardzo stary post, ale możemy używać właściwości Values ​​dokładnie w taki sam sposób, jak DataTokens

Url.RequestContext.RouteData.Values ​​["action"] zadziałało dla mnie.

Joao Nunes da Silva
źródło
0

Nie wiem dlaczego, ale zaakceptowana odpowiedź nie działa. Zwraca null z np. (Może o mvc, używam .net core)

http: // localhost: 5000 / Admin / CustomerGroup

Zawsze debuguję zmienną i pobieram z niej dane.

Spróbuj tego. Mi to pasuje

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

Szczegółowy przykład logiczny

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
fthopkins
źródło