Define the current route in the tag helper. Is it possible?

In an ASP.NET MVC 6 project, I have the following:

[Route("help/how-it-works")]
public IActionResult HowItWorks() {
   return View();
}

I want to create a tag helper as follows:

<a class="menu" asp-controller="Help" asp-action="HowItWorks" route-is="help/how-it-works" css-class="active">How it works</a>

So, the route-check tag helper will check if the current route is “help / how-it-works” ... If it adds “active” to the css class of tag A.

So, I started creating a tag helper:

[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

My problem is how to determine if the current route is "help / how-it-works", and if it adds the Css class to tag A without changing anything else.

Does anyone know how to do this?

UPDATE 1

The problem with duplicate values ​​when using attribute routing has been resolved and an alternative approach proposed by Daniel JG has been added

[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
+4
source share
3

, <a>, MVC AnchorTagHelper. , _ViewImports.cshtml :

@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*, WebApplication5"

, , TagHelperOutput href, AnchorTagHelper, asp-controller asp-action.

//Get url from href attribute generated by the default AnchorTagHelper
var url = output.Attributes["href"].Value.ToString();

URL- , :

var currentRoutUrl = this.urlHelper.Action();

, . ! __ route_group ArgumentException: :

var currentRouteUrl = this.urlHelper.RouteUrl(
                               this.actionContextAccessor.ActionContext.RouteData.Values);

URL- . , URL- "/" "//", Home )

, :

  • <a>, highlight-active. ( css , ):

  • highlight-active html

  • 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);
        }
    }
}

, /:

<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>

( URL / / //):

<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>

PS. , , href ( , href base.Process). URL- ( httpContext.Request).

+6

. . , , , - , TagHelpers TagHelperSamples GitHub, Helper Bootstrap. , , : -)

:

<nav-link asp-controller="Home" asp-action="Index">
  <a asp-controller="Home" asp-action="Index">Blog</a>
</nav-link>
Hide result
+2

Quick and dirty update for DotNetCore 1.0 ...

[HtmlTargetElement("a", Attributes = "highlight-active")]
public class RouteTagHelper : TagHelper
{
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    private IUrlHelperFactory _urlHelper { get; set; }

    public RouteTagHelper(IUrlHelperFactory urlHelper)
    {
        _urlHelper = urlHelper;
    }

    [HtmlAttributeName("css-active-class")]
    public string CssClass { get; set; } = "active";

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.Remove(output.Attributes["highlight-active"]);

        var urlHelper = _urlHelper.GetUrlHelper(ViewContext);

        var url = output.Attributes["href"].Value.ToString();

        if (urlHelper.Action() == url)
        {
            var linkTag = new TagBuilder("a");
            linkTag.Attributes.Add("class", this.CssClass);
            output.MergeAttributes(linkTag);
        }
    }
}
+2
source

Source: https://habr.com/ru/post/1610013/


All Articles