如何将“active”类添加到ASP.NET MVC中的Html.ActionLink

时间:2013-12-05 21:02:11

标签: asp.net css asp.net-mvc twitter-bootstrap

我正在尝试将一个“活动”类添加到MVC中的引导程序导航栏中,但以下内容在显示时不显示活动类:

<ul class="nav navbar-nav">
  <li>@Html.ActionLink("Home", "Index", "Home", null, new {@class="active"})</li>
  <li>@Html.ActionLink("About", "About", "Home")</li>
  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

这解析为看起来像格式正确的类,但不起作用:

<a class="active" href="/">Home</a>

在Bootstrap文档中,它指出不应在导航栏中使用'a'标签,但以上是我认为将类添加到Html.ActionLink的正确方法。我可以做另一种(整洁的)方式吗?

28 个答案:

答案 0 :(得分:266)

在Bootstrap中,active类需要应用于<li>元素,而不是<a>。请参阅此处的第一个示例:http://getbootstrap.com/components/#navbar

基于活动与否的方式处理UI样式的方式与ASP.NET MVC的ActionLink帮助程序无关。这是遵循Bootstrap框架构建方式的正确解决方案。

<ul class="nav navbar-nav">
    <li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

修改

由于您很可能会在多个页面上重复使用您的菜单,因此有一种方法可以根据当前页面自动应用所选类,而不是多次复制菜单并手动执行。

最简单的方法是简单地使用ViewContext.RouteData中包含的值,即ActionController值。我们可以建立在你现在拥有的东西上:

<ul class="nav navbar-nav">
    <li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Index" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
    <li class="@(ViewContext.RouteData.Values["Action"].ToString() == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
    <li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

它在代码中并不漂亮,但它可以完成工作,并允许您根据需要将菜单提取到局部视图中。有一些方法可以更清洁的方式做到这一点,但既然你刚刚开始我会留下它。祝你好运学习ASP.NET MVC!


延迟编辑:

这个问题似乎得到了一些流量,所以我想我会使用HtmlHelper扩展来提供更优雅的解决方案。

编辑03-24-2015:必须重写此方法以允许多个操作和控制器触发所选行为,以及处理从子操作部分视图调用方法时,我认为我将共享更新!

public static string IsSelected(this HtmlHelper html, string controllers = "", string actions = "", string cssClass = "selected")
{
    ViewContext viewContext = html.ViewContext;
    bool isChildAction = viewContext.Controller.ControllerContext.IsChildAction;

    if (isChildAction)
        viewContext = html.ViewContext.ParentActionViewContext;

    RouteValueDictionary routeValues = viewContext.RouteData.Values;
    string currentAction = routeValues["action"].ToString();
    string currentController = routeValues["controller"].ToString();

    if (String.IsNullOrEmpty(actions))
        actions = currentAction;

    if (String.IsNullOrEmpty(controllers))
        controllers = currentController;

    string[] acceptedActions = actions.Trim().Split(',').Distinct().ToArray();
    string[] acceptedControllers = controllers.Trim().Split(',').Distinct().ToArray();

    return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ?
        cssClass : String.Empty;
}

适用于.NET Core:

public static string IsSelected(this IHtmlHelper htmlHelper, string controllers, string actions, string cssClass = "selected")
{
    string currentAction = htmlHelper.ViewContext.RouteData.Values["action"] as string;
    string currentController = htmlHelper.ViewContext.RouteData.Values["controller"] as string;

    IEnumerable<string> acceptedActions = (actions ?? currentAction).Split(',');
    IEnumerable<string> acceptedControllers = (controllers ?? currentController).Split(',');

    return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ?
        cssClass : String.Empty;
}

样本用法:

<ul>
    <li class="@Html.IsSelected(actions: "Home", controllers: "Default")">
        <a href="@Url.Action("Home", "Default")">Home</a>
    </li>
    <li class="@Html.IsSelected(actions: "List,Detail", controllers: "Default")">
        <a href="@Url.Action("List", "Default")">List</a>
    </li>
</ul>

答案 1 :(得分:28)

扩展:

public static MvcHtmlString LiActionLink(this HtmlHelper html, string text, string action, string controller)
{
    var context = html.ViewContext;
    if (context.Controller.ControllerContext.IsChildAction)
        context = html.ViewContext.ParentActionViewContext;
    var routeValues = context.RouteData.Values;
    var currentAction = routeValues["action"].ToString();
    var currentController = routeValues["controller"].ToString();

    var str = String.Format("<li role=\"presentation\"{0}>{1}</li>",
        currentAction.Equals(action, StringComparison.InvariantCulture) &&
        currentController.Equals(controller, StringComparison.InvariantCulture) ?
        " class=\"active\"" :
        String.Empty, html.ActionLink(text, action, controller).ToHtmlString()
    );
    return new MvcHtmlString(str);
}

用法:

<ul class="nav navbar-nav">
    @Html.LiActionLink("About", "About", "Home")
    @Html.LiActionLink("Contact", "Contact", "Home")
</ul>

答案 2 :(得分:18)

我通过在asp.net mvc中添加一个视图包参数来实现这一点。我在做什么

在每个页面中添加了ViewBag.Current = "Scheduler";个参数

在布局页面

<ul class="nav navbar-nav">
     <li class="@(ViewBag.Current == "Scheduler" ? "active" : "") "><a href="@Url.Action("Index","Scheduler")" target="_self">Scheduler</a></li>
 </ul>

这解决了我的问题。

答案 3 :(得分:11)

可能会迟到一点。但希望这会有所帮助。

<script>
$(document).ready(function(){
    $("input").keypress(function(){
        data-name=" value that user puts should come here "
    });
});
</script>

用法如下:

public static class Utilities
{
    public static string IsActive(this HtmlHelper html, 
                                  string control,
                                  string action)
    {
        var routeData = html.ViewContext.RouteData;

        var routeAction = (string)routeData.Values["action"];
        var routeControl = (string)routeData.Values["controller"];

        // both must match
        var returnActive = control == routeControl &&
                           action == routeAction;

        return returnActive ? "active" : "";
    }
}

获得http://www.codingeverything.com/2014/05/mvcbootstrapactivenavbar.html

的参考资料

答案 4 :(得分:6)

我知道这个问题已经过时了,但我想在这里加上我的声音。我认为将链接是否处于活动状态的知识留给视图的控制器是个好主意。

我只想为控制器动作中的每个视图设置一个唯一值。例如,如果我想让主页链接处于活动状态,我会做这样的事情:

public ActionResult Index()
{            
    ViewBag.Title = "Home";
    ViewBag.Home = "class = active";
    return View();
}

然后在我看来,我会写这样的东西:

<li @ViewBag.Home>@Html.ActionLink("Home", "Index", "Home", null, new { title = "Go home" })</li>

当你导航到另一个页面时,比如程序,ViewBag.Home不存在(而不是ViewBag.Programs);因此,没有任何东西被渲染,甚至不是class =“”。我认为这对于可维护性和清洁度来说都更清洁。我倾向于总是希望尽可能多地将逻辑排除在视野之外。

答案 5 :(得分:4)

对于Asp.net MCV 5,此解决方案很简单。

  1. 创建一个静态类,例如Utilitarios.cs

  2. 在Class中创建一个静态方法:

    public static string IsLinkActive(this UrlHelper url, string action, string controller)
    {
        if (url.RequestContext.RouteData.Values["controller"].ToString() == controller &&
            url.RequestContext.RouteData.Values["action"].ToString() == action)
        {
            return "active";
        }
    
        return "";
    }
    
  3. 像这样打电话

    <ul class="sidebar-menu" data-widget="tree">
        <li class="header">HEADER</li>
        <li class="@Url.IsLinkActive("Index", "Home")">
            <a href="@Url.Action("Index", "Home")"><i class="fa fa-link"></i> <span>Home</span></a>
        </li>
        <li class="@Url.IsLinkActive("About", "Home")">
            <a href="@Url.Action("About", "Home")"><i class="fa fa-link"></i><span>About</span></a>
        </li>
    </ul>
    

答案 6 :(得分:3)

可以使用lambda函数

@{
string controllerAction = ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString();
    Func<string, string> IsSelected= x => x==controllerAction ? "active" : "";
}

然后使用

 @Html.ActionLink("Inicio", "Index", "Home", new { area = "" }, new { @class = IsSelected("HomeIndex")})

答案 7 :(得分:3)

你可以试试这个: 在我的情况下,我基于基于角色的访问从数据库加载菜单,根据您的视图在您的每个视图上编写您想要激活的菜单的代码。

<script type="text/javascript">
        $(document).ready(function () {         
            $('li.active active-menu').removeClass('active active-menu');
            $('a[href="/MgtCustomer/Index"]').closest('li').addClass('active active-menu');
        });
</script>

答案 8 :(得分:2)

添加'.ToString'以改进ASP.NET MVC上的比较

<ul class="nav navbar-nav">
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Index" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>

-

答案 9 :(得分:2)

考虑到Damith发布的内容,我认为您可以通过 Viewbag.Title 来确定活跃资格(最佳做法是在您的内容页面中填充此内容以允许您的_Layout.cshtml页面保留你的链接吧)。另请注意,如果您使用子菜单项,它也可以正常工作:

<li class="has-sub @(ViewBag.Title == "Dashboard 1" || ViewBag.Title == "Dashboard 2" ? "active" : "" )">
    <a href="javascript:;">
        <b class="caret"></b>
        <i class="fa fa-th-large"></i>
        <span>Dashboard</span>
    </a>
    <ul class="sub-menu">
        <li class="@(ViewBag.Title == "Dashboard 1" ? "active" : "")"><a href="index.html">Dashboard v1</a></li>
        <li class="@(ViewBag.Title == "Dashboard 2" ? "active" : "")"><a href="index_v2.html">Dashboard v2</a></li>
    </ul>
</li>

答案 10 :(得分:1)

关于此问题的大多数解决方案都要求您在 li a(通过 HtmlHelper)标记上指定“页面”。 @Wolles@Crush 的答案都消除了这种重复,这很好,但他们使用的是 HtmlHelper 扩展方法而不是 TagHelpers。我想使用 TagHelper 支持 Razor Pages。

您可以阅读my full post here(并获取源代码),但其要点是:

<bs-menu-link asp-page="/Events/Index" menu-text="Events"></bs-menu-link>

将呈现(如果链接明显处于活动状态):

<li class="active"><a href="/Events">Events</a></li>

My TagHelper 在内部利用 AnchorTagHelper(因此支持 asp-page、asp-controller、asp-action 等属性)。活动与否的“检查”类似于这篇文章的许多答案。

答案 11 :(得分:1)

我相信这是一个更简洁的代码,可以使所选菜单处于“活动”状态:

AuthorType

 <ul class="navbar-nav mr-auto">
                <li class="nav-item @Html.IfSelected("Index")">
                    <a class="nav-link" href="@Url.Action("Index", "Home")">Home</a>
                </li>
                <li class="nav-item @Html.IfSelected("Controls")">
                    <a class="nav-link" href="@Url.Action("Controls", "Home")">MVC Controls</a>
                </li>
                <li class="nav-item @Html.IfSelected("About")">
                    <a class="nav-link" href="@Url.Action("About", "Home")">About</a>
                </li>
</ul>

答案 12 :(得分:1)

我意识到这个问题对于我们中的一些人来说是一个常见的问题,所以我使用nuget包发布了我自己的解决方案。下面你可以看到它是如何工作的。我希望这会有用。

注意:这个nuget包是我的第一个包。因此,如果您发现错误,请提供反馈。谢谢。

  1. 安装包或下载源代码并添加您的项目

    -Install-Package Betalgo.MvcMenuNavigator
    
  2. 将您的网页添加到枚举

    public enum HeaderTop
    {
        Dashboard,
        Product
    }
    public enum HeaderSub
    {
        Index
    }
    
  3. 将过滤器置于Controllor或Action

    的顶部
    [MenuNavigator(HeaderTop.Product, HeaderSub.Index)]
    public class ProductsController : Controller
    {
        public async Task<ActionResult> Index()
        {
            return View();
        }
    
        [MenuNavigator(HeaderTop.Dashboard, HeaderSub.Index)]
        public async Task<ActionResult> Dashboard()
        {
            return View();
        }
    }
    
  4. 并在您的标题布局中使用它

    @{
    var headerTop = (HeaderTop?)MenuNavigatorPageDataNavigatorPageData.HeaderTop;
    var headerSub = (HeaderSub?)MenuNavigatorPageDataNavigatorPageData.HeaderSub;
    }
    <div class="nav-collapse collapse navbar-collapse navbar-responsive-collapse">
    <ul class="nav navbar-nav">
        <li class="@(headerTop==HeaderTop.Dashboard?"active selected open":"")">
            <a href="@Url.Action("Index","Home")">Dashboard</a>
        </li>
        <li class="@(headerTop==HeaderTop.Product?"active selected open":"")">
            <a href="@Url.Action("Index", "Products")">Products</a>
        </li>
    </ul>
    

  5. 更多信息:https://github.com/betalgo/MvcMenuNavigator

答案 13 :(得分:1)

我修改了dom's "not pretty" answer并使其变得更加丑陋。有时两个控制器具有冲突的动作名称(即索引)所以我这样做:

<ul class="nav navbar-nav">
  <li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "HomeIndex" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
  <li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "AboutIndex" ? "active" : "")">@Html.ActionLink("About", "Index", "About")</li>
  <li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "ContactHome" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

答案 14 :(得分:1)

我也在寻找解决方案,jQuery帮助了很多。首先,您需要为您的<li>元素提供“id”。

<li id="listguides"><a href='/Guides/List'>List Guides</a></li>

在您的布局页面中执行此操作后,您可以告诉jQuery在您的视图中应该“选择”哪个<li>元素。

@section Scripts{
    <script type="text/javascript">
        $('#listguides').addClass('selected');
    </script>
}

注意:您需要在布局页面中@RenderSection("scripts", required: false)</body>标记之前添加该部分。

答案 15 :(得分:1)

我们也可以从RequestContext创建newFonts,我们可以从MvcHandler本身获取它。因此,我相信那些想要在Razor模板中保持这种逻辑的人会有所帮助:

  1. 在项目根目录中创建名为UrlHelper的文件夹。
  2. 创建名为AppCode
  3. 的文件
  4. 在那里创建一个帮助器:

    HtmlHelpers.cshtml
  5. 然后我们就可以使用这样的观点:

    @helper MenuItem(string action, string controller)
    {
         var mvcHandler = Context.CurrentHandler as MvcHandler;
         if (mvcHandler != null)
         {
             var url = new UrlHelper(mvcHandler.RequestContext);
             var routeData = mvcHandler.RequestContext.RouteData;
             var currentAction = routeData.Values["action"].ToString();
             var currentController = routeData.Values["controller"].ToString();
             var isCurrent = string.Equals(currentAction, action, StringComparison.InvariantCultureIgnoreCase) &&
                             string.Equals(currentController, controller, StringComparison.InvariantCultureIgnoreCase);
    
            <div class="@(isCurrent ? "active" : "")">
                <div>@url.Action(action, controller)</div>
            </div>
         }   
    }
    
  6. 希望对某人有所帮助。

答案 16 :(得分:1)

@dombenoit的答案有效。虽然它引入了一些代码来维护。检查这个语法:

using (var nav = Html.Bootstrap().Begin(new Nav().Style(NavType.NavBar).SetLinksActiveByControllerAndAction()))
{
    @nav.ActionLink("Link 1", "action1")
    @nav.ActionLink("Link 2", "action2")
    @nav.Link("External Link", "#")
}

请注意使用.SetLinksActiveByControllerAndAction()方法。

如果您想知道是什么使这种语法成为可能,请查看TwitterBootstrapMVC

答案 17 :(得分:0)

我找到了多条路线的解决方案。 标签助手:

[HtmlTargetElement("li", Attributes = "active-when")]
    public class ActiveTagHelper : TagHelper
    {
        [HtmlAttributeName("active-when")]
        public string ActiveWhen { get; set; }

        [ViewContext]
        [HtmlAttributeNotBound]
        public ViewContext ViewContext { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (ActiveWhen == null)
                return;

            var hrefs = ActiveWhen.Split(",");

            var currentController = ViewContext.RouteData.Values["controller"].ToString();
            var currentAction = ViewContext.RouteData.Values["action"].ToString();

            foreach (var item in hrefs)
            {
                var targetController = item.Split("/")[1];
                var targetAction = item.Split("/")[2];

                if (currentController.Equals(targetController) && currentAction.Equals(targetAction))
                {
                    if (output.Attributes.ContainsName("class"))
                    {
                        output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
                    }
                    else
                    {
                        output.Attributes.SetAttribute("class", "active");
                    }
                }
            }
        }
    }

导入:

@addTagHelper *, YourProjectName

用法:

   <li class="nav-item" active-when="/Product/Index,/Product/Add"></li>

答案 18 :(得分:0)

轻松的ASP.NET Core 3.0和TagHelpers

[HtmlTargetElement("li", Attributes = "active-when")]
public class LiTagHelper : TagHelper
{
    public string ActiveWhen { get; set; }

    [ViewContext]
    [HtmlAttributeNotBound]
    public ViewContext ViewContextData { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (ActiveWhen == null)
            return;

        var targetController = ActiveWhen.Split("/")[1];
        var targetAction = ActiveWhen.Split("/")[2];

        var currentController = ViewContextData.RouteData.Values["controller"].ToString();
        var currentAction = ViewContextData.RouteData.Values["action"].ToString();

        if (currentController.Equals(targetController) && currentAction.Equals(targetAction))
        {
            if (output.Attributes.ContainsName("class"))
            {
                output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
            }
            else
            {
                output.Attributes.SetAttribute("class", "active");
            }
        }
    }
}

包含在您的_ViewImports.cs中:

@addTagHelper *, YourAssemblyName

用法:

 <li active-when="/Home/Index">

答案 19 :(得分:0)

如果它根本没有显示,原因是你需要两个@符号:

@@class

但是,我相信你可能需要让“li”标签上的活动课程不在“a”标签上。根据引导文档(http://getbootstrap.com/components/#navbar-default):

<ul class="nav navbar-nav">
  <li class="active"><a href="#">Home</a></li>
  <li><a href="#">Profile</a></li>
  <li><a href="#">Messages</a></li>
</ul>

因此您的代码将是:

<ul class="nav navbar-nav">
  <li class="active">@Html.ActionLink("Home", "Index", "Home", null)</li>
  <li>@Html.ActionLink("About", "About", "Home")</li>
  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

答案 20 :(得分:0)

ASP.NET Core和Bootstrap 4

最新答案

我已经重新设计了@crush的简洁解决方案,以更新的 ASP.NET Core Bootstrap 4 兼容方式来解决此问题, IHtmlHelper扩展方法:

public static class LinkExtensions
{
    public static IHtmlContent ActiveActionLink(this IHtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        return ActiveActionLink(html, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static IHtmlContent ActiveActionLink(this IHtmlHelper html, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        var routeData = html.ViewContext.RouteData;
        var routeAction = (string)routeData.Values["action"];
        var routeController = (string)routeData.Values["controller"];

        var active = controllerName.Equals(routeController) && actionName.Equals(routeAction);

        using (var writer = new StringWriter())
        {
            writer.WriteLine($"<li class='nav-item {(active ? "active" : "")}'>");
            html.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes).WriteTo(writer, HtmlEncoder.Default);
            writer.WriteLine("</li>");
            return new HtmlString(writer.ToString());
        }
    }
}

用法

<nav class="navbar">
    <div class="collapse navbar-collapse">
        <ul class="navbar-nav">
            @Html.ActiveActionLink("Home", "Index", "Home", null, new { @class = "nav-link" })
            @Html.ActiveActionLink("About", "About", "Home", null, new { @class = "nav-link" })
            @Html.ActiveActionLink("Contact", "Contact", "TimeTracking", null, new { @class = "nav-link" })
        </ul>
    </div>
</nav>

答案 21 :(得分:0)

我这样做了:

在菜单局部视图中创建助手

 @helper RouterLink(string action, string controller)
{
    var IsActive = ViewContext.RouteData.Values["Controller"].ToString() == controller && ViewContext.RouteData.Values["Action"].ToString() == action;
    <text>href="@Url.Action(action, controller)"</text>if (IsActive){ <text>class="active"</text>}
}

然后在锚标记中使用它,如下所示:

<li><a @RouterLink("Index","Home")>Home</a></li>

我的应用程序没有区域,但是它也可以作为另一个变量包含在辅助函数中。我将活动类传递给锚标签。但是li也可以这样配置。

答案 22 :(得分:0)

我创建了一个HtmlHelper扩展名,为想要向链接本身而不是链接周围的ActiveActionLink添加“活动”类的人添加了<li>方法。


public static class LinkExtensions
{
    public static MvcHtmlString ActiveActionLink(this HtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        return ActiveActionLink(html, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString ActiveActionLink(this HtmlHelper html, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        const string activeClassName = "active";

        var routeData = html.ViewContext.RouteData;

        var routeAction = (string)routeData.Values["action"];
        var routeController = (string)routeData.Values["controller"];

        var active = controllerName.Equals(routeController) && actionName.Equals(routeAction);

        if (active)
        {
            var @class = (string)htmlAttributes["class"];

            htmlAttributes["class"] = string.IsNullOrEmpty(@class)
                ? activeClassName
                : @class + " active";
        }

        var link = html.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);

        return link;
    }
}

用法如下:

@Html.ActiveActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-item nav-link" })

答案 23 :(得分:0)

我对此问题的解决方案是

<li class="@(Context.Request.Path.Value.ToLower().Contains("about") ? "active " : "" ) nav-item">
                <a class="nav-link" asp-area="" asp-controller="Home" asp-action="About">About</a>
            </li>

更好的方法是添加Html扩展方法以返回要与链接

进行比较的当前路径

答案 24 :(得分:0)

我已经将上面的答案组合起来并提出了我的解决方案。

所以......

首先在razor块中创建一个字符串变量,该变量将包含控制器的名称值和用户调用的操作。

    @{
        string controllerAction =  ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString(); 
    }

然后使用HTML和Razor代码的组合:

    <ul class="nav navbar-nav">
        <li class="@(controllerAction == "HomeIndex" ? "active" : "" )">@Html.ActionLink("Home", "Index", "Home")</li>
        <li class="@(controllerAction == "AboutIndex" ? "active" : "" )">@Html.ActionLink("About", "Index", "About")</li>
        <li class="@(controllerAction == "HomeContact" ? "active" : "" )">@Html.ActionLink("Contact", "Contact", "Home")</li>
    </ul>

我认为,这很好,因为您不需要访问&#34; ViewContext.RouteData.Values&#34;每次获取控制器名称和操作名称。

答案 25 :(得分:0)

我想提出这个基于Dom答案第一部分的解决方案。

我们首先定义两个变量,&#34; action&#34;和&#34;控制器&#34;并使用它们来确定活动链接:

{ string controller = ViewContext.RouteData.Values["Controller"].ToString();
string action = ViewContext.RouteData.Values["Action"].ToString();}

然后:

<ul class="nav navbar-nav">
    <li class="@((controller == "Home" && action == "Index") ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
    <li class="@((controller == "Home" && action == "About") ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
    <li class="@((controller == "Home" && action == "Contact") ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

现在它看起来更好,不需要更复杂的解决方案。

答案 26 :(得分:0)

希望这会有所帮助,下面是您的菜单:

 <ul class="nav navbar-nav">
   <li><a href="@Url.Action("Index", "Home")" class="@IsMenuSelected("Index","Home", "active")">Home</a></li>
   <li><a href="@Url.Action("About", "Home")" class="@IsMenuSelected("About", "Home", "active")">About</a></li>
   <li><a href="@Url.Action("Contact", "Home")" class="@IsMenuSelected("Contact", "Home", "active")">Contact</a></li>
 </ul>

并在html标记下面添加以下MVC帮助函数。

 @helper IsMenuSelected(string actionName, string controllerName, string className)
    {
            var conname = ViewContext.RouteData.Values["controller"].ToString().ToLower();
            var actname = ViewContext.RouteData.Values["action"].ToString().ToLower();

            if (conname == controllerName.ToLower() && actname == actionName.ToLower())
        {
            @className;
        }
    }

我参考了http://questionbox.in/add-active-class-menu-link-html-actionlink-asp-net-mvc/

的答案

答案 27 :(得分:-1)

ASP.NET Core & Bootstrap 4 & AdminLte

[HtmlTargetElement("a", Attributes = "active-then")]
[HtmlTargetElement("a", Attributes = "asp-action")]
[HtmlTargetElement("a", Attributes = "asp-controller")]
public class AnchorActiveTagHelper : AnchorTagHelper
{
    public AnchorActiveTagHelper(IHtmlGenerator generator) : base(generator)
    {
    }

    [HtmlAttributeName("active-then")]
    public string ActiveWhen { get; set; }

    [ViewContext] [HtmlAttributeNotBound] public ViewContext ViewContextData { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        base.Process(context, output);
        
        if (ActiveWhen == null)
            return;

        var currentController = ViewContextData.RouteData.Values["controller"].ToString();
        var currentAction = ViewContextData.RouteData.Values["action"].ToString();

        if (currentController.Equals(Controller) && currentAction.Equals(Action))
        {
            if (output.Attributes.ContainsName("class"))
            {
                output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
            }
            else
            {
                output.Attributes.SetAttribute("class", "active");
            }
        }
    }
}    

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, YourProject.PlatformExtensions

使用

<li class="nav-item">
    <a asp-controller="Home" asp-action="Index" class="nav-link" active-then="active">
       <i class="nav-icon fas fa-home"></i>
       <p>Home</p>
    </a>
</li>

感谢@WoIIe 和@Shahab