Получить текущее имя области в представлении или контроллере

126

Как получить текущее имя области в представлении или контроллере?

Есть ли что-нибудь подобное ViewContext.RouteData.Values["controller"]для областей?

user202448
источник

Ответы:

217

Начиная с MVC2, вы можете использовать ViewContext.RouteData.DataTokens["area"]

artvolk
источник
22
Если не в области, ViewContext.RouteData.DataTokens ["area"] == null.
user202448
23
... и в MVC5 :)
Стефан
4
Лол .. шутка над тобой, @Dante ... честно говоря, это называется ASP.NET Core 1.0вместо MVC6.. :-)
Росди Касим
FYI - выяснил, что было не так с моим ajax POST, не работал ... пожалуйста, проверьте, что ваши запросы ajax имеют область в URL-адресе ... они все еще могут найти !!! представление, но они не будут поддерживать область ... если в URL-адресе отсутствует область при выполнении запроса.
Seabizkit
43
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
Slava
источник
3
Это лучший и универсальный способ получить информацию об области, если вы не находитесь в представлении или контроллере. Спасибо, что разместили это!
bdrelling 02
19

Вы можете получить его с контроллера, используя:

ControllerContext.RouteData.DataTokens["area"]
Мэтт Пеннер
источник
@ user202338 Области были введены в MVC2, поэтому я подозреваю, что это так, но я не уверен, изменили ли они способ заполнения коллекции DataTokens. Я действительно вижу такие сообщения: ссылка , в которых говорится об использовании этого в MVC2.
Мэтт Пеннер
10

В ASP.NET Core 1.0 значение находится в

ViewContext.RouteData.Values ​​[ "область"];

zerox981
источник
Ты уверен? Насколько я помню, он работал, когда мы запускали наше приложение на ASP.NET Core 2.0, и все еще работает сейчас в ASP.NET Core 2.1 (проверено несколько минут назад).
zerox981
Вы правы, не работает только для Razor Pages (нет ViewContext - pageModel.RouteData.Values.TryGetValue("area", out object area)следует использовать вместо этого)
Роман Покровский
9

Я только что написал об этом в журнале , вы можете посетить это для получения более подробной информации, но мой ответ заключался в создании метода расширения, показанного ниже.

Ключевым моментом было то, что вы извлекаете область MVC из .DataTokens и контроллер / действие из .Values ​​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;
    }

Затем вы можете реализовать это, как показано ниже:

<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
источник
По какой-то причине я не могу найти areaтокен в, Valuesно мне нужно было посмотреть в DataTokens... не знаю почему.
Syska
8

Я создал метод расширения, RouteDataкоторый возвращает текущее имя области.

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

    return null;
}

Поскольку RouteDataдоступен на обоих, ControllerContextи к ViewContextнему можно получить доступ в вашем контроллере и представлениях.

Также очень легко протестировать:

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

Нет необходимости проверять, RouteData.DataTokensявляется ли значение null, поскольку оно всегда инициализируется внутренне.

Бен Фостер
источник
3

MVC Futures имеет метод AreaHelpers.GetAreaName (). Однако будьте осторожны, если используете этот метод. Использование текущей области для принятия решений во время выполнения для вашего приложения может привести к трудному отладке или небезопасному коду.

Леви
источник
1
Есть ли такой метод для контроллеров? Я ненавижу использовать строковые литералы в коллекции.
Erick T
для использования контроллера this.GetName()и для текущего использования методаMethodBase.GetCurrentMethod().Name
Nerdroid
3

Я знаю, что это старый, но также, когда в фильтре, таком как ActionFilter, контекст не легко предоставляет вам информацию об области.

Его можно найти в следующем коде:

var routeData = filterContext.RequestContext.RouteData;

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

Таким образом, filterContext передается при переопределении, а правильные RouteData находятся в RequestContext. На базовом уровне есть RoutData, но у DataTokens НЕТ области в словаре.

gcoleman0828
источник
2

Чтобы получить имя области в представлении, в ASP.NET Core MVC 2.1:

@Context.GetRouteData().Values["area"]
Netstep
источник
2

Получить имя области в представлении (.NET Core 2.2):

ViewContext?.ActionDescriptor?.RouteValues["area"]
SZL
источник
0

Я знаю, что это очень старый пост, но мы можем использовать свойство Values ​​точно так же, как DataTokens.

Url.RequestContext.RouteData.Values ​​["действие"] работал у меня.

Жоао Нуньес да Силва
источник
0

Я не знаю почему, но принятый ответ не работает. Он возвращает null, например, (возможно, о mvc, я использую ядро ​​.net)

HTTP: // локальный: 5000 / Admin / CustomerGroup

Я всегда отлаживаю переменную и беру данные из нее.

Попробуй это. Меня устраивает

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

Подробный логический пример

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
fthopkins
источник