Как получить текущее имя области в представлении или контроллере?
Есть ли что-нибудь подобное ViewContext.RouteData.Values["controller"]
для областей?
Как получить текущее имя области в представлении или контроллере?
Есть ли что-нибудь подобное ViewContext.RouteData.Values["controller"]
для областей?
Ответы:
Начиная с MVC2, вы можете использовать ViewContext.RouteData.DataTokens["area"]
ASP.NET Core 1.0
вместо MVC6
.. :-)
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
Вы можете получить его с контроллера, используя:
ControllerContext.RouteData.DataTokens["area"]
В ASP.NET Core 1.0 значение находится в
ViewContext.RouteData.Values [ "область"];
pageModel.RouteData.Values.TryGetValue("area", out object area)
следует использовать вместо этого)
Я только что написал об этом в журнале , вы можете посетить это для получения более подробной информации, но мой ответ заключался в создании метода расширения, показанного ниже.
Ключевым моментом было то, что вы извлекаете область 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>
area
токен в, Values
но мне нужно было посмотреть в DataTokens
... не знаю почему.
Я создал метод расширения, 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, поскольку оно всегда инициализируется внутренне.
MVC Futures имеет метод AreaHelpers.GetAreaName (). Однако будьте осторожны, если используете этот метод. Использование текущей области для принятия решений во время выполнения для вашего приложения может привести к трудному отладке или небезопасному коду.
this.GetName()
и для текущего использования методаMethodBase.GetCurrentMethod().Name
Я знаю, что это старый, но также, когда в фильтре, таком как ActionFilter, контекст не легко предоставляет вам информацию об области.
Его можно найти в следующем коде:
var routeData = filterContext.RequestContext.RouteData;
if (routeData.DataTokens["area"] != null)
area = routeData.DataTokens["area"].ToString();
Таким образом, filterContext передается при переопределении, а правильные RouteData находятся в RequestContext. На базовом уровне есть RoutData, но у DataTokens НЕТ области в словаре.
Я знаю, что это очень старый пост, но мы можем использовать свойство Values точно так же, как DataTokens.
Url.RequestContext.RouteData.Values ["действие"] работал у меня.
Я не знаю почему, но принятый ответ не работает. Он возвращает null, например, (возможно, о mvc, я использую ядро .net)
Я всегда отлаживаю переменную и беру данные из нее.
Попробуй это. Меня устраивает
var area = ViewContext.RouteData.Values["area"]
Подробный логический пример
Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";