Подтвердить что ты не робот

Лучший способ получить ссылку на главную страницу MVC 3 Razor

Когда я хочу, чтобы определенная ссылка на меню была активной на данной странице, я использую этот подход в Razor:

На макете мастера у меня есть эти проверки:

var active = ViewBag.Active;
const string ACTIVE_CLASS = "current";

if (active == "home")
{
    ViewBag.ActiveHome = ACTIVE_CLASS;
}
if (active == "products")
{
    ViewBag.ActiveProducts = ACTIVE_CLASS;
}

и др.

Меню html в макете макета:

<ul>
<li class="@ViewBag.ActiveHome"><a href="/">Home</a></li>
<li class="@ViewBag.ActiveProducts"><a href="@Url.Action("index", "products")">Products</a></li>
</ul>

При указании страницы макета для использования на другом представлении:

@{
    ViewBag.Active = "home";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Есть ли лучший подход для разделения активных ссылок, чем тот, который я сейчас использую?

4b9b3361

Ответ 1

Лучший подход заключается в использовании HTML-помощника:

using System.Web.Mvc; 
using System.Web.Mvc.Html;

public static class MenuExtensions
{
    public static MvcHtmlString MenuItem(
        this HtmlHelper htmlHelper, 
        string text,
        string action, 
        string controller
    )
    {
        var li = new TagBuilder("li");
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.GetRequiredString("action");
        var currentController = routeData.GetRequiredString("controller");
        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }
        li.InnerHtml = htmlHelper.ActionLink(text, action, controller).ToHtmlString();
        return MvcHtmlString.Create(li.ToString());
    }
}

а затем:

<ul>
    @Html.MenuItem("Home", "Home", "Home")
    @Html.MenuItem("Products", "Index", "Products")
</ul>

Для выполнения вышеуказанной работы вам понадобятся ваши взгляды, чтобы узнать ваше расширение: в Web.config в папке "Виды" добавьте <add namespace="yourNamespacehere.Helpers" /> внутри тега пространств имен. Затем создайте проект и закройте и снова откройте представление, которое вы добавляете.

тогда на основе текущего действия и контроллера хелпер добавит или не класс active при создании якоря.

Ответ 2

Развернувшись на примере Дарина, здесь полный класс, который добавляет дополнительные дополнительные параметры для RouteValues ​​и HtmlAttributes в помощнике. По сути, он ведет себя так же, как базовый ActionLink.

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MYNAMESPACE.Helpers {
    public static class MenuExtensions {
        public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper,
                                             string text, string action,
                                             string controller,
                                             object routeValues = null,
                                             object htmlAttributes = null) {
            var li = new TagBuilder("li");
            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString("action");
            var currentController = routeData.GetRequiredString("controller");
            if (string.Equals(currentAction,
                              action,
                              StringComparison.OrdinalIgnoreCase) &&
                string.Equals(currentController,
                              controller,
                              StringComparison.OrdinalIgnoreCase)) {
                li.AddCssClass("active");
            }
            if (routeValues != null) {
                li.InnerHtml = (htmlAttributes != null)
                    ? htmlHelper.ActionLink(text,
                                            action,
                                            controller,
                                            routeValues,
                                            htmlAttributes).ToHtmlString()
                    : htmlHelper.ActionLink(text, 
                                            action, 
                                            controller, 
                                            routeValues).ToHtmlString();
            }
            else {
                li.InnerHtml = htmlHelper.ActionLink(text, 
                                                     action, 
                                                     controller).ToHtmlString();
            }
            return MvcHtmlString.Create(li.ToString());
        }
    }
}

И в папке View web.config:

<system.web.webPages.razor>
  <host ... />
  <pages ... >
    <namespaces>
      ...

      ...
      <add namespace="MYNAMESPACE.Helpers" />
    </namespaces>
  </pages>
</system.web.webPages.razor>

Ответ 3

Используйте этот InnerHtml, если вы хотите включить форматирование HTML в свой текст;

li.InnerHtml = "<a href=\"" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(action, controller).ToString() + "\">" + text + "</a>";

текст может быть "<b> Bold </b> Normal";

Ответ 4

Обновлено для RC2. Для тех, кто задается вопросом, как это сделать в MVC6/Asp.Net 5 - похоже, но тонко отличается. Теперь нет MvcHtmlString, а RouteData работает совершенно по-другому. Кроме того, теперь объект контекста должен быть IHtmlContent, а не HtmlHelper.

using System;
using Microsoft.AspNet.Mvc.Rendering;

public static class MenuExtensions
{
    public static IHtmlContent MenuItem(
        this IHtmlHelper htmlHelper,
        string text,
        string action,
        string controller
    )
    {

        var li = new TagBuilder("li") { TagRenderMode = TagRenderMode.Normal };
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.Values["action"].ToString();
        var currentController = routeData.Values["controller"].ToString();

        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }


        li.InnerHtml.AppendHtml(htmlHelper.ActionLink(text, action, controller));

        return li;


    }
}

Ответ 5

Этот код отлично подойдет для меня, даже в новом проекте MVC5/Bootstrap Visual Studio 2013. Также обратите внимание, что вы можете изменить li.AddCssClass( "active" ); line, чтобы указать на пользовательский класс, если вы хотите оставить только активный класс Bootstrap. Я добавил один из них "activemenu" в файле Site.css проекта и сделал какие-то изменения в стиле навигации, которые я хотел там.

Линия в приведенном выше коде была просто изменена на это, чтобы заставить все это работать:

li.AddCssClass("activemenu");

В Site.css я добавил простой класс для своей цели:

.activemenu {
    text-decoration: underline;
}

В качестве альтернативы вы можете изменить цвет фона и/или границу и т.д.

Ответ 6

здесь есть расширение для класса Darin для вставки html в текст ссылки, а не простой текст

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace YourNameSpaceHere
{
    public static class MenuExtensions
    {
        public static MvcHtmlString MenuItem(
            this HtmlHelper htmlHelper,
            string html,
            string action,
            string controller
        )
        {
            var li = new TagBuilder("li");
            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString("action");
            var currentController = routeData.GetRequiredString("controller");
            if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
                string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
            {
                li.AddCssClass("active");
            }
            //generate a unique id for the holder and convert it to string
            string holder = Guid.NewGuid().ToString();
            string anchor = htmlHelper.ActionLink(holder, action, controller).ToHtmlString();
            //replace the holder string with the html
            li.InnerHtml = anchor.Replace(holder, html);
            return MvcHtmlString.Create(li.ToString());
        }
    }
}

и используйте его следующим образом:

<ul>
    @Html.MenuItem("<span class'ClassName'>Home</span>", "Home", "Home")
</ul>