49 votes

Comment réaliser des fils d'Ariane dynamiques avec ASP.net MVC ?

Comment chapelure dynamique être réalisé avec ASP.net MVC ?

Si vous êtes curieux de savoir ce que sont les miettes de pain :

Qu'est-ce que la chapelure ? Si vous avez déjà navigué sur une boutique en ligne ou lu des messages dans un forum, vous avez probablement rencontré des fils d'Ariane. Ils constituent un moyen facile de savoir où vous vous trouvez sur un site. Des sites comme Craigslist utilisent le fil d'Ariane pour décrire l'emplacement de l'utilisateur. Au-dessus des annonces de chaque page se trouve quelque chose qui ressemble à ceci :

s.f. bayarea craigslist > ville de san francisco > bicyclettes

EDIT

Je sais ce qui est possible avec le SiteMapProvider. Je suis également conscient des fournisseurs qui existent sur le net et qui vous permettent d'associer les sitenodes aux contrôleurs et aux actions.

Mais qu'en est-il lorsque vous souhaitez que le texte d'un fil d'Ariane corresponde à une valeur dynamique, comme ceci :

Accueil > Produits > Voitures > Toyota

Accueil > Produits > Voitures > Chevy

Accueil > Produits > Équipement d'exécution > Chaise électrique

Accueil > Produits > Équipement d'exécution > Potences

... où les catégories de produits et les produits sont des enregistrements d'une base de données. Certains liens doivent être définis de manière statique (Home pour sûr).

J'essaie de comprendre comment faire cela, mais je suis sûr que quelqu'un l'a déjà fait avec ASP.net MVC.

2voto

Ronnie Overby Points 11402

MvcSiteMapProvider de Maarten Balliauw a plutôt bien fonctionné pour moi.

J'ai créé une petite application mvc pour tester son fournisseur : Test de MvcSiteMapProvider (404)

2voto

SmartDev Points 73

Pour ceux qui sont intéressés, j'ai fait une version améliorée d'une HtmlExtension qui prend également en compte les zones et utilise en outre Reflection pour vérifier s'il existe un contrôleur par défaut dans une zone ou une action d'index dans un contrôleur :

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

Si peut certainement être amélioré (ne couvre probablement pas tous les cas possibles), mais il ne m'a pas fait défaut jusqu'à présent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X