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.

2voto

Ronnie Overby Punkte 43323

Der MvcSiteMapProvider von Maarten Balliauw hat bei mir ziemlich gut funktioniert.

Ich habe eine kleine mvc-App erstellt, um seinen Anbieter zu testen: MvcSiteMapProvider Test (404)

2voto

SmartDev Punkte 2742

Für alle, die es interessiert, habe ich eine verbesserte Version eines HtmlExtension die auch Bereiche berücksichtigt und zusätzlich Reflection verwendet, um zu prüfen, ob es einen Standard-Controller innerhalb eines Bereichs oder eine Index-Aktion innerhalb eines Controllers gibt:

public static class HtmlExtensions
    {
        public static MvcHtmlString BuildBreadcrumbNavigation(this HtmlHelper helper)
        {
            string area = (helper.ViewContext.RouteData.DataTokens["area"] ?? "").ToString();
            string controller = helper.ViewContext.RouteData.Values["controller"].ToString();
            string action = helper.ViewContext.RouteData.Values["action"].ToString();

            // add link to homepage by default
            StringBuilder breadcrumb = new StringBuilder(@"
                <ol class='breadcrumb'>
                    <li>" + helper.ActionLink("Homepage", "Index", "Home", new { Area = "" }, new { @class="first" }) + @"</li>");

            // add link to area if existing
            if (area != "")
            {
                breadcrumb.Append("<li>");
                if (ControllerExistsInArea("Default", area)) // by convention, default Area controller should be named Default
                {
                    breadcrumb.Append(helper.ActionLink(area.AddSpaceOnCaseChange(), "Index", "Default", new { Area = area }, new { @class = "" }));
                }
                else
                {
                    breadcrumb.Append(area.AddSpaceOnCaseChange());
                }
                breadcrumb.Append("</li>");
            }

            // add link to controller Index if different action
            if ((controller != "Home" && controller != "Default") && action != "Index")
            {
                if (ActionExistsInController("Index", controller, area))
                {
                    breadcrumb.Append("<li>");
                    breadcrumb.Append(helper.ActionLink(controller.AddSpaceOnCaseChange(), "Index", controller, new { Area = area }, new { @class = "" }));
                    breadcrumb.Append("</li>");
                }
            }

            // add link to action
            if ((controller != "Home" && controller != "Default") || action != "Index")
            {
                breadcrumb.Append("<li>");
                //breadcrumb.Append(helper.ActionLink((action.ToLower() == "index") ? controller.AddSpaceOnCaseChange() : action.AddSpaceOnCaseChange(), action, controller, new { Area = area }, new { @class = "" }));
                breadcrumb.Append((action.ToLower() == "index") ? controller.AddSpaceOnCaseChange() : action.AddSpaceOnCaseChange());
                breadcrumb.Append("</li>");
            }

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

        public static Type GetControllerType(string controller, string area)
        {
            string currentAssembly = Assembly.GetExecutingAssembly().GetName().Name;
            IEnumerable<Type> controllerTypes = Assembly.GetExecutingAssembly().GetTypes().Where(o => typeof(IController).IsAssignableFrom(o));

            string typeFullName = String.Format("{0}.Controllers.{1}Controller", currentAssembly, controller);
            if (area != "")
            {
                typeFullName = String.Format("{0}.Areas.{1}.Controllers.{2}Controller", currentAssembly, area, controller);
            }

            return controllerTypes.Where(o => o.FullName == typeFullName).FirstOrDefault();
        }

        public static bool ActionExistsInController(string action, string controller, string area)
        {
            Type controllerType = GetControllerType(controller, area);
            return (controllerType != null && new ReflectedControllerDescriptor(controllerType).GetCanonicalActions().Any(x => x.ActionName == action));
        }

        public static bool ControllerExistsInArea(string controller, string area)
        {
            Type controllerType = GetControllerType(controller, area);
            return (controllerType != null);
        }

    public static string AddSpaceOnCaseChange(this string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return "";
        StringBuilder newText = new StringBuilder(text.Length * 2);
        newText.Append(text[0]);
        for (int i = 1; i < text.Length; i++)
        {
            if (char.IsUpper(text[i]) && text[i - 1] != ' ')
                newText.Append(' ');
            newText.Append(text[i]);
        }
        return newText.ToString();
    }
}

Kann definitiv verbessert werden (deckt wahrscheinlich nicht alle möglichen Fälle ab), aber es hat mich bis jetzt nicht enttäuscht.

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