Como você obtém o nome da área atual na visualização ou no controlador?
Existe algo parecido ViewContext.RouteData.Values["controller"]
com áreas?
Como você obtém o nome da área atual na visualização ou no controlador?
Existe algo parecido ViewContext.RouteData.Values["controller"]
com áreas?
Respostas:
A partir do MVC2, você pode usar ViewContext.RouteData.DataTokens["area"]
ASP.NET Core 1.0
em vez de MVC6
.. :-)
Você pode obtê-lo do controlador usando:
ControllerContext.RouteData.DataTokens["area"]
No ASP.NET Core 1.0, o valor é encontrado em
ViewContext.RouteData.Values ["area"];
pageModel.RouteData.Values.TryGetValue("area", out object area)
deve ser usado em vez)
Acabei de escrever uma entrada de log sobre isso , você pode visitar isso para obter mais detalhes, mas minha resposta foi criar um método de extensão, mostrado abaixo.
O ponto principal foi que você extraiu a Área MVC do .DataTokens e o controlador / ação dos .Values do 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;
}
Então você pode implementá-lo como abaixo:
<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 no, Values
mas precisava procurar no DataTokens
... não faço ideia do porquê.
Eu criei um método de extensão para RouteData
que retorne o nome da área atual.
public static string GetAreaName(this RouteData routeData)
{
object area;
if (routeData.DataTokens.TryGetValue("area", out area))
{
return area as string;
}
return null;
}
Uma vez que RouteData
está disponível em ambos ControllerContext
e ViewContext
pode ser acessado em seu controlador e visualizações.
Também é muito fácil testar:
[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();
}
}
Não há necessidade de verificar se RouteData.DataTokens
é nulo, pois isso sempre é inicializado internamente.
O MVC Futures possui um método AreaHelpers.GetAreaName (). No entanto, tenha cuidado se você estiver usando esse método. Usar a área atual para tomar decisões de tempo de execução sobre seu aplicativo pode levar a códigos difíceis de depurar ou inseguros.
this.GetName()
e para o atual uso MétodoMethodBase.GetCurrentMethod().Name
Sei que isso é antigo, mas também, quando em um filtro como o ActionFilter, o contexto não fornece facilmente as informações da área.
Pode ser encontrado no seguinte código:
var routeData = filterContext.RequestContext.RouteData;
if (routeData.DataTokens["area"] != null)
area = routeData.DataTokens["area"].ToString();
Portanto, o filterContext está sendo transmitido na substituição e o RouteData correto é encontrado no RequestContext. Há um RoutData no nível Base, mas os DataTokens NÃO possuem a área em seu dicionário.
Eu sei que esta é uma postagem muito antiga, mas podemos usar a propriedade Values exatamente da mesma maneira que os DataTokens
Url.RequestContext.RouteData.Values ["action"] funcionou para mim.
Não sei por que, mas a resposta aceita não está funcionando. Ele retorna nulo com, por exemplo (talvez sobre mvc, eu uso .net core)
Eu sempre depuro a variável e busco dados nela.
Tente isso. Funciona para mim
var area = ViewContext.RouteData.Values["area"]
Exemplo lógico detalhado
Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";