web-dev-qa-db-fra.com

Comment puis-je avoir des itinéraires en minuscules dans ASP.NET MVC?

Comment puis-je avoir des itinéraires en minuscules, plus des traits de soulignement si possible, dans ASP.NET MVC? Pour que je demande à /dinners/details/2 D'appeler DinnersController.Details(2) et, si possible, /dinners/more_details/2 D'appeler DinnersController.MoreDetails(2)?

Tout cela tout en utilisant des modèles comme {controller}/{action}/{id}.

144
pupeno

Avec System.Web.Routing 4.5, vous pouvez implémenter cela simplement en définissant la propriété LowercaseUrls de RouteCollection:

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.LowercaseUrls = true;

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

En supposant également que vous le faites pour des raisons de référencement, vous souhaitez rediriger les URL entrantes en minuscules (comme indiqué dans de nombreux liens de cet article).

protected void Application_BeginRequest(object sender, EventArgs e)
{
  //You don't want to redirect on posts, or images/css/js
  bool isGet = HttpContext.Current.Request.RequestType.ToLowerInvariant().Contains("get");
  if (isGet && HttpContext.Current.Request.Url.AbsolutePath.Contains(".") == false)    
  {
     string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
     if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
     {
      //You don't want to change casing on query strings
      lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;

      Response.Clear();
      Response.Status = "301 Moved Permanently";
      Response.AddHeader("Location", lowercaseURL); 
      Response.End();
    }
 }
}
233
ITmeze

Ces deux tutoriels m'ont aidé lorsque je voulais faire la même chose et bien travailler:

http://www.coderjournal.com/2008/03/force-mvc-route-url-lowercase/http://goneale.com/2008/12/19/lowercase -route-urls-in-aspnet-mvc /

EDIT: pour les projets avec des zones, vous devez modifier la méthode GetVirtualPath ():

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
  var lowerCaseValues = new RouteValueDictionary();

  foreach (var v in values)
  {
    switch (v.Key.ToUpperInvariant())
    {
      case "ACTION":
      case "AREA":
      case "CONTROLLER":
        lowerCaseValues.Add(v.Key, ((string)v.Value).ToLowerInvariant());
        break;
      default:
        lowerCaseValues.Add(v.Key.ToLowerInvariant(), v.Value);
        break;
    }
  }
  return base.GetVirtualPath(requestContext, lowerCaseValues);
}
44
Derek Lawless

Si vous utilisez UrlHelper pour générer le lien, vous pouvez simplement spécifier le nom de l'action et du contrôleur en minuscules:

itemDelete.NavigateUrl = Url.Action("delete", "photos", new { key = item.Key });

Résultats dans:/media/photos/delete/64 (même si mon contrôleur et mon action sont en cas Pascal).

21
Matt

S'il vous arrivait d'utiliser ASP.NET Core, vous devriez probablement jeter un œil à this :

Ajoutez la ligne suivante à la méthode ConfigureServices de la classe Startup.

services.AddRouting(options => options.LowercaseUrls = true);
18
Ebrahim Byagowi

Je l'ai trouvé dans Coder Journal de Nick Berardi , mais il ne contenait aucune information sur la façon d'implémenter la classe LowercaseRoute. Par conséquent, republiez ici avec des informations supplémentaires.

Étendez d'abord la classe Route à LowercaseRoute

public class LowercaseRoute : Route
{
    public LowercaseRoute(string url, IRouteHandler routeHandler)
        : base(url, routeHandler) { }
    public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
        : base(url, defaults, routeHandler) { }
    public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
        : base(url, defaults, constraints, routeHandler) { }
    public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, defaults, constraints, dataTokens, routeHandler) { }
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        VirtualPathData path = base.GetVirtualPath(requestContext, values);

        if (path != null)
            path.VirtualPath = path.VirtualPath.ToLowerInvariant();

        return path;
    }
}

Modifiez ensuite la méthode RegisterRoutes de Global.asax.cs

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add(new LowercaseRoute("{controller}/{action}/{id}", 
        new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }), 
        new MvcRouteHandler()));

    //routes.MapRoute(
    //    "Default",                                              // Route name
    //    "{controller}/{action}/{id}",                           // URL with parameters
    //    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    //);
}

Je voudrais cependant savoir comment utiliser les routes. MapRoute ...

15
John Oxley

Vous pouvez continuer à utiliser la syntaxe MapRoute en ajoutant cette classe en tant qu'extension à RouteCollection:

public static class RouteCollectionExtension
{
    public static Route MapRouteLowerCase(this RouteCollection routes, string name, string url, object defaults)
    {
        return routes.MapRouteLowerCase(name, url, defaults, null);
    }

    public static Route MapRouteLowerCase(this RouteCollection routes, string name, string url, object defaults, object constraints)
    {
        Route route = new LowercaseRoute(url, new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(defaults),
            Constraints = new RouteValueDictionary(constraints)
        };

        routes.Add(name, route);

        return route;
    }
}

Vous pouvez maintenant utiliser dans le démarrage de votre application "MapRouteLowerCase" au lieu de "MapRoute":

    public void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // Url shortcuts
        routes.MapRouteLowerCase("Home", "", new { controller = "Home", action = "Index" });
        routes.MapRouteLowerCase("Login", "login", new { controller = "Account", action = "Login" });
        routes.MapRouteLowerCase("Logout", "logout", new { controller = "Account", action = "Logout" });

        routes.MapRouteLowerCase(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );
    }
11
Markus Wolters

Cela a en fait deux réponses:

  1. Vous pouvez déjà le faire: le moteur de routage effectue une comparaison insensible à la casse. Si vous saisissez une route en minuscules, elle sera acheminée vers le contrôleur et l'action appropriés.
  2. Si vous utilisez des contrôles qui génèrent des liens de route (ActionLink, RouteLink, etc.), ils produiront des liens à casse mixte, sauf si vous remplacez ce comportement par défaut.

Vous êtes seul pour les soulignés, cependant ...

6
GalacticCowboy

Pourriez-vous utiliser l'attribut ActionName?

 [ActionName("more_details")]
 public ActionResult MoreDetails(int? page)
 {

 }

Je ne pense pas que l'affaire soit importante. More_Details, more_DETAILS, mOrE_DeTaILs dans l'URL vous mènent tous à la même action de contrôleur.

2
GuyIncognito