在视图或控制器中获取当前区域名称


126

如何在视图或控制器中获取当前区域名称?

有什么类似ViewContext.RouteData.Values["controller"]的地方吗?

Answers:


217

从MVC2开始,您可以使用 ViewContext.RouteData.DataTokens["area"]


22
如果不在区域中,则ViewContext.RouteData.DataTokens [“ area”] == null。
user202448'5

23
...以及在MVC5中:)
Stefan

4
哈哈..开玩笑在您身上@Dante ...好吧,它被称为ASP.NET Core 1.0而不是MVC6.. :-)
Rosdi Kasim

仅供参考-找出我的ajax POST出了什么问题无法正常工作...请检查您的ajax请求在URL中是否包含该区域...他们仍然可以找到!!视图,但他们不会保留该区域...如果在发出请求时url缺少该区域。
Seabizkit

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

3
如果您不在视图或控制器中,这是获取区域信息的最佳通用方法。感谢您发布!
凌晨

19

您可以使用以下方法从控制器获取它:

ControllerContext.RouteData.DataTokens["area"]

@ user202338 MVC2中引入了区域,所以我怀疑是这样,但是我不确定它们是否改变了填充DataTokens集合的方式。我确实看到了这样的文章: 链接,谈到在MVC2中使用它的情况。
马特·彭纳

10

在ASP.NET Core 1.0中,该值位于

ViewContext.RouteData.Values [“ area”];


你确定吗?据我所记得,它在我们在ASP.NET Core 2.0上运行我们的应用程序时有效,并且现在仍在ASP.NET Core 2.1中运行(此刻已经过测试)。
zerox981 '18 -10-30

您是对的,不是仅适用于Razor Pages(没有ViewContext- pageModel.RouteData.Values.TryGetValue("area", out object area)应该使用)
Roman Pokrovskij

9

我只是为此写了一个日志条目,您可以访问它以获取更多详细信息,但是我的答案是创建一个扩展方法,如下所示。

关键因素是您从.DataTokens中拉出MVC区域,并从RouteData的.Values中拉出控制器/动作。

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>

由于某种原因,我无法在中找到area令牌,Values但需要查找DataTokens...。不知道为什么。
Syska 2014年

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期货具有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,并在RequestContext下找到正确的RouteData。在基础级别上有一个RoutData,但是DataTokens的字典中没有该区域。


2

要在视图中获取区域名称,请在ASP.NET Core MVC 2.1中:

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

2

在View(.NET Core 2.2)中获取区域名称:

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

0

我知道这是一个非常老的帖子,但是我们可以使用与DataTokens完全相同的方式使用Values属性

Url.RequestContext.RouteData.Values [“ action”]为我工作。


0

我不知道为什么,但是接受的答案不起作用。它用例如返回null(也许关于mvc,我使用.net core)

http:// localhost:5000 / Admin / CustomerGroup

我总是调试变量并从中获取数据。

试试这个。这个对我有用

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

详细的逻辑示例

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.