Jak uzyskać bieżącą nazwę obszaru w widoku lub kontrolerze?
Czy jest coś podobnego ViewContext.RouteData.Values["controller"]
do obszarów?
Jak uzyskać bieżącą nazwę obszaru w widoku lub kontrolerze?
Czy jest coś podobnego ViewContext.RouteData.Values["controller"]
do obszarów?
Odpowiedzi:
Od MVC2 możesz używać ViewContext.RouteData.DataTokens["area"]
ASP.NET Core 1.0
zamiast MVC6
.. :-)
Możesz go pobrać z kontrolera za pomocą:
ControllerContext.RouteData.DataTokens["area"]
W ASP.NET Core 1.0 wartość znajduje się w
ViewContext.RouteData.Values ["obszar"];
pageModel.RouteData.Values.TryGetValue("area", out object area)
należy go zamiast tego użyć)
Właśnie napisałem wpis w dzienniku ab na ten temat , możesz go odwiedzić, aby uzyskać więcej informacji, ale moją odpowiedzią było utworzenie metody rozszerzenia, pokazanej poniżej.
Kluczowym kicker było to, że wyciągasz obszar MVC z .DataTokens, a kontroler / akcja z .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;
}
Następnie możesz to zaimplementować jak poniżej:
<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
tokena w, Values
ale musiałem zajrzeć do DataTokens
... nie mam pojęcia dlaczego.
Stworzyłem metodę rozszerzenia, RouteData
która zwraca bieżącą nazwę obszaru.
public static string GetAreaName(this RouteData routeData)
{
object area;
if (routeData.DataTokens.TryGetValue("area", out area))
{
return area as string;
}
return null;
}
Ponieważ RouteData
jest dostępny na obu ControllerContext
i ViewContext
można uzyskać do niego dostęp w kontrolerze i widokach.
Bardzo łatwo jest też przetestować:
[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();
}
}
Nie ma potrzeby sprawdzania, czy RouteData.DataTokens
jest null, ponieważ jest to zawsze inicjowane wewnętrznie.
MVC Futures ma metodę AreaHelpers.GetAreaName (). Jednak zachowaj ostrożność, jeśli używasz tej metody. Używanie bieżącego obszaru do podejmowania decyzji dotyczących aplikacji w czasie wykonywania może prowadzić do trudnego do debugowania lub niezabezpieczonego kodu.
this.GetName()
i do bieżącego użycia metodyMethodBase.GetCurrentMethod().Name
Wiem, że to jest stare, ale także w filtrze takim jak ActionFilter kontekst nie zapewnia łatwo informacji o obszarze.
Można go znaleźć w następującym kodzie:
var routeData = filterContext.RequestContext.RouteData;
if (routeData.DataTokens["area"] != null)
area = routeData.DataTokens["area"].ToString();
Tak więc filterContext jest przekazywana w przypadku zastąpienia, a poprawne RouteData znajduje się w RequestContext. Istnieje RoutData na poziomie podstawowym, ale DataTokens NIE mają obszaru w swoim słowniku.
Wiem, że to bardzo stary post, ale możemy używać właściwości Values dokładnie w taki sam sposób, jak DataTokens
Url.RequestContext.RouteData.Values ["action"] zadziałało dla mnie.
Nie wiem dlaczego, ale zaakceptowana odpowiedź nie działa. Zwraca null z np. (Może o mvc, używam .net core)
Zawsze debuguję zmienną i pobieram z niej dane.
Spróbuj tego. Mi to pasuje
var area = ViewContext.RouteData.Values["area"]
Szczegółowy przykład logiczny
Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";