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}
.
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();
}
}
}
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);
}
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).
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 classeStartup
.services.AddRouting(options => options.LowercaseUrls = true);
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 ...
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
);
}
Cela a en fait deux réponses:
Vous êtes seul pour les soulignés, cependant ...
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.