Come si ottiene il nome dell'area corrente nella vista o nel controller?
C'è qualcosa di simile ViewContext.RouteData.Values["controller"]
per le aree?
Come si ottiene il nome dell'area corrente nella vista o nel controller?
C'è qualcosa di simile ViewContext.RouteData.Values["controller"]
per le aree?
Risposte:
Da MVC2 in poi puoi usare ViewContext.RouteData.DataTokens["area"]
ASP.NET Core 1.0
invece di MVC6
.. :-)
Puoi ottenerlo dal controller usando:
ControllerContext.RouteData.DataTokens["area"]
In ASP.NET Core 1.0 il valore si trova in
ViewContext.RouteData.Values [ "area"];
pageModel.RouteData.Values.TryGetValue("area", out object area)
dovrebbe essere usato invece)
Ho appena scritto una voce di registro su questo , puoi visitarlo per maggiori dettagli, ma la mia risposta è stata quella di creare un metodo di estensione, mostrato di seguito.
Il kicker chiave è stato estrarre l'Area MVC da .DataTokens e il controller / azione dai .Values di 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;
}
Quindi puoi implementarlo come di seguito:
<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
token nel Values
ma avevo bisogno di guardare nel DataTokens
... non ho idea del perché.
Ho creato un metodo di estensione per RouteData
quello restituisce il nome dell'area corrente.
public static string GetAreaName(this RouteData routeData)
{
object area;
if (routeData.DataTokens.TryGetValue("area", out area))
{
return area as string;
}
return null;
}
Poiché RouteData
è disponibile su entrambi ControllerContext
e ViewContext
è possibile accedervi dal controller e dalle visualizzazioni.
È anche molto facile testare:
[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();
}
}
Non è necessario verificare se RouteData.DataTokens
è null poiché è sempre inizializzato internamente.
MVC Futures ha un metodo AreaHelpers.GetAreaName (). Tuttavia, prestare attenzione se si utilizza questo metodo. L'uso dell'area corrente per prendere decisioni di runtime sull'applicazione potrebbe portare a codici difficili da eseguire il debug o non sicuri.
this.GetName()
e per l'uso del Metodo correnteMethodBase.GetCurrentMethod().Name
So che questo è vecchio, ma anche, quando in un filtro come ActionFilter, il contesto non fornisce facilmente le informazioni sull'area.
Si può trovare nel seguente codice:
var routeData = filterContext.RequestContext.RouteData;
if (routeData.DataTokens["area"] != null)
area = routeData.DataTokens["area"].ToString();
Quindi il filterContext viene passato sull'override e il RouteData corretto viene trovato in RequestContext. C'è un RoutData a livello Base, ma i DataTokens NON hanno l'area nel suo dizionario.
So che questo è un post molto vecchio ma possiamo usare la proprietà Values esattamente allo stesso modo dei DataTokens
Url.RequestContext.RouteData.Values ["action"] ha funzionato per me.
Non so perché ma la risposta accettata non funziona. Restituisce null con es. (Forse su mvc, io uso .net core)
Eseguo sempre il debug della variabile e recupero i dati da essa.
Prova questo. Per me funziona
var area = ViewContext.RouteData.Values["area"]
Esempio logico dettagliato
Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";