Get Current Area Name in View or Controller

前端 未结 12 1497
闹比i
闹比i 2020-11-29 00:50

How do you get the current area name in the view or controller?

Is there anything like ViewContext.RouteData.Values[\"controller\"] for areas?

相关标签:
12条回答
  • 2020-11-29 01:18
    HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
    
    0 讨论(0)
  • 2020-11-29 01:18

    I just wrote a blog entry about this, you can visit that for more details, but my answer was to create an Extension Method, shown below.

    The key kicker was that you pull the MVC Area from the .DataTokens and the controller/action from the .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;
        }
    

    Then you can implement it as below :

    <ul id="menu">
    @Html.TopMenuLink("Dashboard", "Home", "Index", "", "Click here for the dashboard.")
    @Html.TopMenuLink("Courses", "Home", "Index", "Courses", "List of our Courses.")
    </ul>
    
    0 讨论(0)
  • 2020-11-29 01:19

    I created an extension method for RouteData that returns the current area name.

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

    Since RouteData is available on both ControllerContext and ViewContext it can be accessed in your controller and views.

    It is also very easy to test:

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

    There is no need to check if RouteData.DataTokens is null since this always initialized internally.

    0 讨论(0)
  • 2020-11-29 01:22

    You can get it from the controller using:

    ControllerContext.RouteData.DataTokens["area"]
    
    0 讨论(0)
  • 2020-11-29 01:23

    I know this is old, but also, when in a filter like ActionFilter, the context does not easily provide you with the area information.

    It can be found in the following code:

    var routeData = filterContext.RequestContext.RouteData;
    
    if (routeData.DataTokens["area"] != null)
        area = routeData.DataTokens["area"].ToString();
    

    So the filterContext is being passed in on the override and the correct RouteData is found under the RequestContext. There is a RoutData at the Base level, but the DataTokens DO NOT have the area in it's dictionary.

    0 讨论(0)
  • 2020-11-29 01:24

    From MVC2 onwards you can use ViewContext.RouteData.DataTokens["area"]

    0 讨论(0)
提交回复
热议问题