在ASP.NET MVC 6项目中,我有以下内容:
[Route("help/how-it-works")]
public IActionResult HowItWorks() {
return View();
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个标签助手,如下所示:
<a class="menu" asp-controller="Help" asp-action="HowItWorks" route-is="help/how-it-works" css-class="active">How it works</a>
Run Code Online (Sandbox Code Playgroud)
所以route-is标签帮助器将检查当前路由是否为"help/how-it-works"...如果是,则将"active"添加到A标签的css类.
所以我开始创建一个标签助手:
[TargetElement("a", Attributes = "route-is, css-class")]
public class RouteTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
String routeIs = context.AllAttributes["route-is"].ToString();
String cssClass = context.AllAttributes["css-class"].ToString();
if (String.IsNullOrWhiteSpace(cssClass))
cssClass = "active";
ViewContext.RouteData.Values.Keys;
}
}// Process
Run Code Online (Sandbox Code Playgroud)
我的问题是如何确定当前路由是否为"help/how-it-works",以及是否将Css类添加到A标记而不更改其他任何内容.
有没有人知道如何做到这一点?
更新1
使用属性路由时解决了重复值的问题,并添加了Daniel JG提出的替代方法
[TargetElement("a", Attributes = RouteIsName)]
[TargetElement("a", Attributes = RouteHasName)]
public class ActiveRouteTagHelper : TagHelper
{
private const String RouteIsName = "route-is";
private const String RouteHasName = "route-has";
private const String RouteCssName = "route-css";
private IActionContextAccessor _actionContextAccessor;
private IUrlHelper _urlHelper;
[HtmlAttributeName(RouteCssName)]
public String RouteCss { get; set; } = "active";
[HtmlAttributeName(RouteHasName)]
public String RouteHas { get; set; }
[HtmlAttributeName(RouteIsName)]
public String RouteIs { get; set; }
public ActiveRouteTagHelper(IActionContextAccessor actionContextAccessor, IUrlHelper urlHelper)
{
_actionContextAccessor = actionContextAccessor;
_urlHelper = urlHelper;
} // ActiveRouteTagHelper
public override void Process(TagHelperContext context, TagHelperOutput output)
{
IDictionary<String, Object> values = _actionContextAccessor.ActionContext.RouteData.Values;
String route = _urlHelper.RouteUrl(values.Distinct()).ToLowerInvariant();
Boolean match = false;
if (!String.IsNullOrWhiteSpace(RouteIs))
{
match = route == RouteIs;
} else {
if (RouteHas != null) {
String[] keys = RouteHas.Split(',');
if (keys.Length > 0)
match = keys.All(x => route.Contains(x.ToLowerInvariant()));
}
}
if (match)
{
TagBuilder link = new TagBuilder("a");
link.AddCssClass(RouteCss);
output.MergeAttributes(link);
}
} // Process
} // ActiveRouteTagHelper
Run Code Online (Sandbox Code Playgroud)
您可以利用<a>与默认MVC 相同的元素AnchorTagHelper.您只需要确保在默认的_ViewImports.cshtml中添加助手:
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*, WebApplication5"
Run Code Online (Sandbox Code Playgroud)
然后,无论何时执行帮助程序,TagHelperOutput都将包含使用和标记由默认生成的href.AnchorTagHelperasp-controllerasp-action
//Get url from href attribute generated by the default AnchorTagHelper
var url = output.Attributes["href"].Value.ToString();
Run Code Online (Sandbox Code Playgroud)
然后,您可以将该URL与将为当前请求生成的URL进行比较:
var currentRoutUrl = this.urlHelper.Action();
Run Code Online (Sandbox Code Playgroud)
最初我尝试了下面的代码,但在使用属性路由时它不起作用.我可以在路由值中看到一个带有键!__ route_group的条目和一个异常ArgumentException:抛出了一个已经添加了相同键的项:
Run Code Online (Sandbox Code Playgroud)var currentRouteUrl = this.urlHelper.RouteUrl( this.actionContextAccessor.ActionContext.RouteData.Values);
这样做而不是比较当前请求URL是有原因的.这样,无论当前请求url是"/"还是"/ Home/Index",在这两种情况下,您都会考虑为控制器Home和action Index激活一个链接)
我按照这个想法创建了一个标签助手:
标记助手将用于<a>已highlight-active定义属性的元素.(这允许css类的属性是可选的,在这种情况下使用默认的活动类):
标记属性highlight-active将从输出html中删除
class属性与属性合并css-active-class(也从输出html中删除)
代码如下:
[HtmlTargetElement("a", Attributes = "highlight-active")]
public class RouteTagHelper : TagHelper
{
private IActionContextAccessor actionContextAccessor;
private IUrlHelper urlHelper;
public RouteTagHelper(IActionContextAccessor actionContextAccessor, IUrlHelper urlHelper)
{
this.actionContextAccessor = actionContextAccessor;
this.urlHelper = urlHelper;
}
//Optional attribute. If not defined, "active" class will be used
[HtmlAttributeName("css-active-class")]
public string CssClass { get; set; } = "active";
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//Remove marker attribute
output.Attributes.Remove(output.Attributes["highlight-active"]);
//Get the url from href attribute generaed in the default AnchorTagHelper
var url = output.Attributes["href"].Value.ToString();
//Add active css class only when current request matches the generated href
var currentRouteUrl = this.urlHelper.Action();
if (url == currentRouteUrl)
{
var linkTag = new TagBuilder("a");
linkTag.Attributes.Add("class", this.CssClass);
output.MergeAttributes(linkTag);
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,您现在可以在主页/索引页面中编写以下内容:
<a class="menu" asp-controller="Home" asp-action="Index" highlight-active>Home</a>
<a class="menu" asp-controller="Home" asp-action="About" highlight-active>About</a>
<a class="menu" asp-controller="Home" asp-action="Index" highlight-active css-active-class="myActiveClass">Home with special class name</a>
<a class="menu" asp-controller="Home" asp-action="Index">Home using default tag helper</a>
Run Code Online (Sandbox Code Playgroud)
其呈现方式如下(无论当前网址是/或/ Home还是/ Home/Index):
<a class="menu active" href="/">Home</a>
<a class="menu" href="/Home/About">About</a>
<a class="menu myActiveClass" href="/">Home with special class</a>
<a class="menu" href="/">Home using default tag helper</a>
Run Code Online (Sandbox Code Playgroud)
PS.当您添加一个直接指定href属性的锚点时,您可能仍需要考虑这些情况(在调用之前,您可以检测是否已经有一个href base.Process).在这种情况下,您可能还希望与当前URL进行比较(通过httpContext.Request).
| 归档时间: |
|
| 查看次数: |
4309 次 |
| 最近记录: |