58 Stimmen

Wie können dynamische Breadcrumbs mit ASP.net MVC erreicht werden?

Wie können dynamische Brotkrümel mit ASP.net MVC erreicht werden?

Wenn Sie wissen möchten, was Paniermehl ist:

Was sind Brotkrümel? Wenn Sie schon einmal in einem Online-Shop gestöbert oder Beiträge in einem Forum gelesen haben, sind Sie wahrscheinlich schon auf Breadcrumbs gestoßen. Sie bieten eine einfache Möglichkeit zu sehen, wo Sie sich auf einer Website befinden. Websites wie Craigslist verwenden Breadcrumbs, um den Standort des Benutzers zu beschreiben. Über den Inseraten auf jeder Seite steht etwas, das so aussieht:

s.f. bayarea craigslist > stadt san francisco > fahrräder

EDIT

Ich weiß, was mit dem SiteMapProvider möglich ist. Ich bin mir auch bewusst, dass es Anbieter im Netz gibt, die es Ihnen ermöglichen, Sitenodes auf Controller und Aktionen abzubilden.

Aber was ist, wenn Sie möchten, dass der Text eines Breadcrumbs mit einem dynamischen Wert übereinstimmt, wie hier:

Startseite > Produkte > Autos > Toyota

Startseite > Produkte > Autos > Chevy

Home > Produkte > Hinrichtungsausrüstung > Elektrischer Stuhl

Home > Produkte > Hinrichtungsausrüstung > Galgen

... wobei die Produktkategorien und die Produkte Datensätze aus einer Datenbank sind. Einige Links sollten statisch definiert werden (Home for sure).

Ich versuche herauszufinden, wie dies zu tun, aber ich bin sicher, jemand hat dies bereits mit ASP.net MVC getan.

70voto

Sean Haddy Punkte 1596

Sitemaps sind definitiv eine Möglichkeit... alternativ können Sie eine selbst schreiben! (natürlich solange die Standard-MVC-Regeln eingehalten werden)... Ich habe gerade eine geschrieben, ich dachte, ich würde hier teilen.

@Html.ActionLink("Home", "Index", "Home")
@if(ViewContext.RouteData.Values["controller"].ToString() != "Home") {
    @:> @Html.ActionLink(ViewContext.RouteData.Values["controller"].ToString(), "Index", ViewContext.RouteData.Values["controller"].ToString()) 
}
@if(ViewContext.RouteData.Values["action"].ToString() != "Index"){
    @:> @Html.ActionLink(ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString()) 
}

Hoffentlich findet das jemand hilfreich, das ist genau das, was ich gesucht habe, als ich SO für MVC Breadcrumbs gesucht habe.

34voto

vulcan raven Punkte 31125

ASP.NET 5 (auch bekannt als ASP.NET Core), MVC Core-Lösung

In ASP.NET Core sind die Dinge weiter optimiert, da wir das Markup in der Erweiterungsmethode nicht stringifizieren müssen.

~/Extesions/HtmlExtensions.cs :

using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace YourProjectNamespace.Extensions
{
    public static class HtmlExtensions
    {
        private static readonly HtmlContentBuilder _emptyBuilder = new HtmlContentBuilder();

        public static IHtmlContent BuildBreadcrumbNavigation(this IHtmlHelper helper)
        {
            if (helper.ViewContext.RouteData.Values["controller"].ToString() == "Home" ||
                helper.ViewContext.RouteData.Values["controller"].ToString() == "Account")
            {
                return _emptyBuilder;
            }

            string controllerName = helper.ViewContext.RouteData.Values["controller"].ToString();
            string actionName = helper.ViewContext.RouteData.Values["action"].ToString();

            var breadcrumb = new HtmlContentBuilder()
                                .AppendHtml("<ol class='breadcrumb'><li>")
                                .AppendHtml(helper.ActionLink("Home", "Index", "Home"))
                                .AppendHtml("</li><li>")
                                .AppendHtml(helper.ActionLink(controllerName.Titleize(),
                                                          "Index", controllerName))
                                .AppendHtml("</li>");

            if (helper.ViewContext.RouteData.Values["action"].ToString() != "Index")
            {
                breadcrumb.AppendHtml("<li>")
                          .AppendHtml(helper.ActionLink(actionName.Titleize(), actionName, controllerName))
                          .AppendHtml("</li>");
            }

            return breadcrumb.AppendHtml("</ol>");
        }
    }
}

~/Extensions/StringExtensions.cs bleibt die gleiche wie unten (scrollen Sie nach unten, um die MVC5-Version zu sehen).

Nach Ansicht von Razor brauchen wir keine Html.Raw da Razor sich um das Entkommen kümmert, wenn es um IHtmlContent :

....
....
<div class="container body-content">

    <!-- #region Breadcrumb -->
    @Html.BuildBreadcrumbNavigation()
    <!-- #endregion -->

    @RenderBody()
    <hr />
...
...

ASP.NET 4, MVC 5 Lösung

\=== ORIGINAL / ALTE ANTWORT UNTEN ===

(In Erweiterung der obigen Antwort von Sean Haddy)

Wenn Sie es erweiterungsgesteuert machen wollen (und Views sauber halten), können Sie etwas tun wie:

~/Extesions/HtmlExtensions.cs :

(kompatibel mit MVC5 / Bootstrap)

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

namespace YourProjectNamespace.Extensions
{
    public static class HtmlExtensions
    {
        public static string BuildBreadcrumbNavigation(this HtmlHelper helper)
        {
            // optional condition: I didn't wanted it to show on home and account controller
            if (helper.ViewContext.RouteData.Values["controller"].ToString() == "Home" ||
                helper.ViewContext.RouteData.Values["controller"].ToString() == "Account")
            {
                return string.Empty;
            }

            StringBuilder breadcrumb = new StringBuilder("<ol class='breadcrumb'><li>").Append(helper.ActionLink("Home", "Index", "Home").ToHtmlString()).Append("</li>");

            breadcrumb.Append("<li>");
            breadcrumb.Append(helper.ActionLink(helper.ViewContext.RouteData.Values["controller"].ToString().Titleize(),
                                               "Index",
                                               helper.ViewContext.RouteData.Values["controller"].ToString()));
            breadcrumb.Append("</li>");

            if (helper.ViewContext.RouteData.Values["action"].ToString() != "Index")
            {
                breadcrumb.Append("<li>");
                breadcrumb.Append(helper.ActionLink(helper.ViewContext.RouteData.Values["action"].ToString().Titleize(),
                                                    helper.ViewContext.RouteData.Values["action"].ToString(),
                                                    helper.ViewContext.RouteData.Values["controller"].ToString()));
                breadcrumb.Append("</li>");
            }

            return breadcrumb.Append("</ol>").ToString();
        }
    }
}

~/Extensions/StringExtensions.cs :

using System.Globalization;
using System.Text.RegularExpressions;

namespace YourProjectNamespace.Extensions
{
    public static class StringExtensions
    {
        public static string Titleize(this string text)
        {
            return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text).ToSentenceCase();
        }

        public static string ToSentenceCase(this string str)
        {
            return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
        }
    }
}

Dann verwenden Sie es wie (zum Beispiel in _Layout.cshtml):

....
....
<div class="container body-content">

    <!-- #region Breadcrumb -->
    @Html.Raw(Html.BuildBreadcrumbNavigation())
    <!-- #endregion -->

    @RenderBody()
    <hr />
...
...

25voto

ICodeForCoffee Punkte 3097

Es gibt ein Tool auf Codeplex, das dies ermöglicht: http://mvcsitemap.codeplex.com/ [Projekt [verschoben nach github]](https://github.com/maartenba/MvcSiteMapProvider)

Edit:

Es gibt eine Möglichkeit, einen SiteMapProvider aus einer Datenbank abzuleiten: http://www.asp.net/Learn/data-access/tutorial-62-cs.aspx

Möglicherweise können Sie das Tool mvcsitemap so ändern, dass Sie das Gewünschte erhalten.

5voto

Larz Punkte 323

Ich habe dieses Nuget-Paket erstellt, um dieses Problem für mich zu lösen:

https://www.nuget.org/packages/MvcBreadCrumbs/

Sie können hier einen Beitrag leisten, wenn Sie Ideen dafür haben:

https://github.com/thelarz/MvcBreadCrumbs

5voto

pim Punkte 10987

Für diejenigen, die ASP.NET Core 2.0 verwenden und nach einem entkoppelteren Ansatz als Vulcans HtmlHelper suchen, empfehle ich einen Blick auf die Verwendung einer partiellen Ansicht mit Dependency Injection .

Im Folgenden finden Sie eine einfache Umsetzung, die sich leicht an Ihre Bedürfnisse anpassen lässt.

Der Brotkrümel-Dienst ( ./Services/BreadcrumbService.cs ):

using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.Collections.Generic;

namespace YourNamespace.YourProject
{  
  public class BreadcrumbService : IViewContextAware
  {
    IList<Breadcrumb> breadcrumbs;

    public void Contextualize(ViewContext viewContext)
    {
      breadcrumbs = new List<Breadcrumb>();

      string area = $"{viewContext.RouteData.Values["area"]}";
      string controller = $"{viewContext.RouteData.Values["controller"]}";
      string action = $"{viewContext.RouteData.Values["action"]}";
      object id = viewContext.RouteData.Values["id"];
      string title = $"{viewContext.ViewData["Title"]}";   

      breadcrumbs.Add(new Breadcrumb(area, controller, action, title, id));

      if(!string.Equals(action, "index", StringComparison.OrdinalIgnoreCase))
      {
        breadcrumbs.Insert(0, new Breadcrumb(area, controller, "index", title));
      }
    }

    public IList<Breadcrumb> GetBreadcrumbs()
    {
      return breadcrumbs;
    }
  }

  public class Breadcrumb
  {
    public Breadcrumb(string area, string controller, string action, string title, object id) : this(area, controller, action, title)
    {
      Id = id;
    }

    public Breadcrumb(string area, string controller, string action, string title)
    {
      Area = area;
      Controller = controller;
      Action = action;

      if (string.IsNullOrWhiteSpace(title))
      {
         Title = Regex.Replace(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string.Equals(action, "Index", StringComparison.OrdinalIgnoreCase) ? controller : action), "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
      }
      else
      {
         Title = title;
      } 
    }

    public string Area { get; set; }
    public string Controller { get; set; }
    public string Action { get; set; }
    public object Id { get; set; }
    public string Title { get; set; }
  }
}

Registrieren Sie den Dienst in startup.cs nach AddMvc() :

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddTransient<BreadcrumbService>(); 

Erstellen Sie einen Teilbereich zum Rendern der Brotkrümel ( ~/Views/Shared/Breadcrumbs.cshtml ):

@using YourNamespace.YourProject.Services
@inject BreadcrumbService BreadcrumbService

@foreach(var breadcrumb in BreadcrumbService.GetBreadcrumbs())
{
    <a asp-area="@breadcrumb.Area" asp-controller="@breadcrumb.Controller" asp-action="@breadcrumb.Action" asp-route-id="@breadcrumb.Id">@breadcrumb.Title</a>
}

Um die Brotkrümel zu rendern, rufen Sie an dieser Stelle einfach Html.Partial("Breadcrumbs") o Html.PartialAsync("Breadcrumbs") .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X