ASP.net prise en charge MVC pour les URL avec des traits d'Union

est-il un moyen facile d'obtenir le MvcRouteHandler pour convertir tous les traits d'Union dans les sections action et controller d'une URL entrante en underscores car les traits d'Union ne sont pas supportés dans les noms de méthode ou de classe.

ce serait pour que je puisse soutenir des structures telles que sample.com/test-page/edit-details mapping to Action edit_details et Controller test_pagecontroller tout en continuant à utiliser la méthode MapRoute.

je comprends que je peux spécifier un l'attribut de nom d'action et les traits d'union de soutien dans les noms de controller qui sortent en ajoutant manuellement des routes pour atteindre ceci cependant je suis à la recherche d'une manière automatisée donc enregistrer des erreurs lors de l'ajout de nouveaux controllers et des actions.

30
demandé sur John 2010-01-15 13:45:40

8 réponses

C # version de John's Post pour tous ceux qui le préféreraient: C# et VB version sur mon blog

public class HyphenatedRouteHandler : MvcRouteHandler{
        protected override IHttpHandler  GetHttpHandler(RequestContext requestContext)
        {
            requestContext.RouteData.Values["controller"] = requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
            requestContext.RouteData.Values["action"] = requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
            return base.GetHttpHandler(requestContext);
        }
    }

...et la nouvelle route:

routes.Add(
            new Route("{controller}/{action}/{id}", 
                new RouteValueDictionary(
                    new { controller = "Default", action = "Index", id = "" }),
                    new HyphenatedRouteHandler())
        );

vous pouvez utiliser la méthode suivante aussi, mais gardez à l'esprit que vous auriez besoin de nommer la vue My-Action qui peut être ennuyeux si vous aimez laisser visual studio auto générer vos fichiers de vue.

[ActionName("My-Action")]
public ActionResult MyAction() {
    return View();
}
31
répondu Andrew 2011-06-29 08:31:21

j'ai trouvé une solution. Le contexte request à l'intérieur du MvcRouteHandler contient les valeurs pour le controller et l'action sur laquelle vous pouvez faire un simple remplacement sur.

Public Class HyphenatedRouteHandler
    Inherits MvcRouteHandler

    Protected Overrides Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler
        requestContext.RouteData.Values("controller") = requestContext.RouteData.Values("controller").ToString.Replace("-", "_")
        requestContext.RouteData.Values("action") = requestContext.RouteData.Values("action").ToString.Replace("-", "_")
        Return MyBase.GetHttpHandler(requestContext)
    End Function

End Class

puis tout ce dont vous avez besoin pour remplacer les routes.MapRoute avec des itinéraires équivalents.Ajouter spécifier le nouveau gestionnaire de route. Ceci est requis car le MapRoute ne vous permet pas de spécifier un gestionnaire de route personnalisé.

routes.Add(New Route("{controller}/{action}/{id}", New RouteValueDictionary(New With {.controller = "Home", .action = "Index", .id = ""}), New HyphenatedRouteHandler()))
18
répondu John 2010-01-16 12:17:55

Tout ce que vous devez vraiment faire dans ce cas est de nommer vos vues avec les traits d'Union que vous voulez qu'elles apparaissent dans L'URL, supprimer les traits d'Union dans votre controller et ensuite ajouter un attribut Actionnom qui a les traits d'union de retour en elle. Il n'y a aucun besoin d'avoir des underscores.

ont une vue appelée modifier-détails.aspx

et avoir un contrôleur comme celui-ci:

[ActionName("edit-details")]
public ActionResult EditDetails(int id)
{
    // your code
}
14
répondu Chris Conway 2011-02-11 13:12:10

je me rends compte que c'est une question assez ancienne, mais pour moi ce n'est que la moitié de l'histoire d'accepter les url avec des traits d'Union en eux, l'autre moitié génère ces urls tout en étant capable d'utiliser Html.ActionLink et d'autres helpers dans le cadre MVC, j'ai résolu cela en créant une classe de route personnalisée similaire, voici le code au cas où il aide quelqu'un à venir ici à partir d'une recherche google. Il comprend également le boîtier inférieur de l'url.

public class SeoFriendlyRoute : Route
{
     // constructor overrides from Route go here, there is 4 of them

     public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
     {
          var path = base.GetVirtualPath(requestContext, values);

          if (path != null)
          {
              var indexes = new List<int>();
              var charArray = path.VirtualPath.Split('?')[0].ToCharArray();
              for (int index = 0; index < charArray.Length; index++)
              {
                  var c = charArray[index];
                  if (index > 0 && char.IsUpper(c) && charArray[index - 1] != '/')
                      indexes.Add(index);
              }

              indexes.Reverse();
              indexes.Remove(0);
              foreach (var index in indexes)
                  path.VirtualPath = path.VirtualPath.Insert(index, "-");

              path.VirtualPath = path.VirtualPath.ToLowerInvariant();
          }

          return path;
     }
}

alors quand en ajoutant des routes, vous pouvez soit créer des extensions RouteCollection ou simplement utiliser ce qui suit dans vos déclarations globales de routage

routes.Add(
        new SeoFriendlyRoute("{controller}/{action}/{id}", 
            new RouteValueDictionary(
                new { controller = "Default", action = "Index", id = "" }),
                new HyphenatedRouteHandler())
    );
9
répondu dsteuernol 2012-06-27 03:59:02

Merci dsteuernol pour cette réponse - exactement ce que je cherchais. Cependant, j'ai trouvé que j'avais besoin d'améliorer le coupleur de traits D'Union pour couvrir le scénario où le contrôleur ou la zone était implicite à partir de la page courante. Par exemple, en utilisant @Html.ActionLink ("Mon Lien"," Index")

j'ai changé la méthode GetHttpHandler pour la suivante:

public class HyphenatedRouteHandler : MvcRouteHandler
    {
        /// <summary>
        /// Returns the HTTP handler by using the specified HTTP context.
        /// </summary>
        /// <param name="requestContext">The request context.</param>
        /// <returns>
        /// The HTTP handler.
        /// </returns>
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {

            requestContext.RouteData.Values["controller"] = ReFormatString(requestContext.RouteData.Values["controller"].ToString());
            requestContext.RouteData.Values["action"] = ReFormatString(requestContext.RouteData.Values["action"].ToString());

            // is there an area
            if (requestContext.RouteData.DataTokens.ContainsKey("area"))
            {
                requestContext.RouteData.DataTokens["area"] = ReFormatString(requestContext.RouteData.DataTokens["area"].ToString());
            }

            return base.GetHttpHandler(requestContext);
        }


        private string ReFormatString(string hyphenedString)
        {
            // lets put capitals back in

            // change dashes to spaces
            hyphenedString = hyphenedString.Replace("-", " ");

            // change to title case
            hyphenedString = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(hyphenedString);

            // remove spaces
            hyphenedString = hyphenedString.Replace(" ", "");

            return hyphenedString;
        }
    }

la remise des majuscules signifiait que le contrôleur implicite ou la zone était alors les mots correctement.

2
répondu Sylvia 2013-03-28 11:18:01

j'ai développé un open source NuGet library pour ce problème qui convertit implicitement EveryMvc/Url en every-mvc/url.

Les URL

sont beaucoup plus conviviales pour le référencement et plus faciles à lire. ( plus sur mon blog )

paquet NuGet: https://www.nuget.org/packages/LowercaseDashedRoute /

pour l'installer, il suffit d'ouvrir la fenêtre NuGet Visual Studio en cliquant avec le bouton droit de la souris sur le projet et en sélectionnant NuGet Package Manager, et sur l'onglet "Online" tapez "Lowercase Dashed Route", et il devrait apparaître.

alternativement, vous pouvez exécuter ce code dans la Console du Gestionnaire de paquets:

Install-Package LowercaseDashedRoute

après cela, vous devez ouvrir App_Start/RouteConfig.cs et commenter route existante.MapRoute(...) appelez et ajoutez ceci à la place:

routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
  new RouteValueDictionary(
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
    new DashedRouteHandler()
  )
);

C'est ça. Toutes les urls sont minuscules, tiretées et converties implicitement sans que vous fassiez quoi que ce soit de plus.

Open Source Url du projet: https://github.com/AtaS/lowercase-dashed-route

1
répondu Ata S. 2013-08-03 11:50:06

Ne sait pas d'une manière sans écrire une carte pour chaque url:

routes.MapRoute("EditDetails", "test-page/edit-details/{id}", new { controller = "test_page", action = "edit_details" });
0
répondu Paul Hiles 2010-01-15 11:09:58

si vous mettez à jour votre projet en MVC5, vous pouvez utiliser l'acheminement des attributs.

[Route("controller/my-action")]
public ActionResult MyAction() {
    return View();
}

je préfère de loin cette approche à la solution acceptée, qui vous laisse avec les underscores dans les noms d'action de votre contrôleur et les noms de fichiers de vue, et les traits d'Union dans L'Url de votre vue.Les aides d'Action. Je préfère la cohérence, et ne pas avoir à me rappeler comment les noms sont convertis.

0
répondu Rob 2017-09-03 12:40:15