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

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

有没有类似 ViewContext.RouteData.Values["controller"]的区域?

72638 次浏览

MVC Futures 有一个 Area Helpers。GetAreaName ()方法。但是,如果使用此方法,请小心使用。使用当前区域对应用程序做出运行时决策可能导致难以调试或不安全的代码。

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

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

ControllerContext.RouteData.DataTokens["area"]

我刚刚写了一个 b关于这个的日志记录,你可以访问它了解更多细节,但我的答案是创建一个扩展方法,如下所示。

关键在于你把 MVC 区域从。控件中的控制器/操作。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>

我知道这已经过时了,但是,当使用 ActionFilter 这样的过滤器时,上下文不能很容易地为您提供区域信息。

它可以在以下代码中找到:

var routeData = filterContext.RequestContext.RouteData;


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

因此,将在覆盖时传递 filterContext,并在 RequestContext 下找到正确的 RouteData。在基本级别有一个 RoutData,但是 DataTokens 在它的字典中没有这个区域。

我为返回当前区域名称的 RouteData创建了一个扩展方法。

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


return null;
}

因为 RouteDataControllerContextViewContext上都可用,所以可以在控制器和视图中访问它。

它也非常容易测试:

[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,因为它总是在内部初始化。

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

我知道这是一篇非常非常老的文章,但是我们可以使用与 DataTokens 完全相同的方式值属性

对我来说,Url.RequestContext.RouteData.Values [“ action”]很有用。

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

值[“区域”] ;

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

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

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

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

我不知道为什么,但接受的答案是不工作。它返回 null,例如(可能是 mvc,我使用。净核)

Http://localhost:5000/admin/customergroup

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

试试这个,对我有用

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

详细的逻辑例子

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";

ASP. Net Core 3.1

场景: 我想在 ViewComponent Invoke 方法中检索当前区域名称。

  public IViewComponentResult Invoke()
{
string areaName = this.RouteData.Values["area"];


//Your code here...


return View(items);
}

在 MVC5中,现在似乎需要这样做。当在 Controller中,将 this.ControllerContext.RouteData传递给这个例程:


/// <summary>
/// Get the name of the Area from the RouteData
/// </summary>
/// <param name="routeData"></param>
/// <returns></returns>
private static string GetArea(RouteData routeData)
{
var area = routeData.DataTokens["area"]?.ToString();
if (area != null)
{
// this used to work
return area;
}


// newer approach
var matchedList = routeData.Values["MS_DirectRouteMatches"] as List<RouteData>;
if (matchedList != null)
{
foreach (var matchedRouteData in matchedList)
{
if (matchedRouteData.DataTokens.TryGetValue("area", out var rawArea))
{
return rawArea.ToString();
}
}
}


return "";
}