Делая URL-адрес в нижнем регистре. Любой простой или встроенный способ?
Есть ли простой/встроенный способ сделать URL в нижнем регистре для MVC3.
У меня есть код, который может сделать это, но выглядит что-то простое в реализации.
routes.MapRouteLowercase(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "index", id = UrlParameter.Optional } // Parameter defaults
);
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;
}
}
public static class RouteCollectionExtensions
{
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url)
{
return routes.MapRouteLowercase(name, url, null /* defaults */, (object)null /* constraints */);
}
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults)
{
return routes.MapRouteLowercase(name, url, defaults, (object)null /* constraints */);
}
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, object constraints)
{
return routes.MapRouteLowercase(name, url, defaults, constraints, null /* namespaces */);
}
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url, string[] namespaces)
{
return routes.MapRouteLowercase(name, url, null /* defaults */, null /* constraints */, namespaces);
}
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, string[] namespaces)
{
return routes.MapRouteLowercase(name, url, defaults, null /* constraints */, namespaces);
}
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
Route route = new LowercaseRoute(url, new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
public static Route MapRouteLowercase(this AreaRegistrationContext context, string name, string url)
{
return context.MapRouteLowercase(name, url, (object)null /* defaults */);
}
public static Route MapRouteLowercase(this AreaRegistrationContext context, string name, string url, object defaults)
{
return context.MapRouteLowercase(name, url, defaults, (object)null /* constraints */);
}
public static Route MapRouteLowercase(this AreaRegistrationContext context, string name, string url, object defaults, object constraints)
{
return context.MapRouteLowercase(name, url, defaults, constraints, null /* namespaces */);
}
public static Route MapRouteLowercase(this AreaRegistrationContext context, string name, string url, string[] namespaces)
{
return context.MapRouteLowercase(name, url, (object)null /* defaults */, namespaces);
}
public static Route MapRouteLowercase(this AreaRegistrationContext context, string name, string url, object defaults, string[] namespaces)
{
return context.MapRouteLowercase(name, url, defaults, null /* constraints */, namespaces);
}
public static Route MapRouteLowercase(this AreaRegistrationContext context, string name, string url, object defaults, object constraints, string[] namespaces)
{
if (namespaces == null && context.Namespaces != null)
{
namespaces = context.Namespaces.ToArray();
}
Route route = context.Routes.MapRouteLowercase(name, url, defaults, constraints, namespaces);
route.DataTokens["area"] = context.AreaName;
// disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up
// controllers belonging to other areas
bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;
return route;
}
}
Ответы
Ответ 1
Я только что заметил, что в .NET Framework 4.5 есть новое свойство. Прекрасно работает!
RouteCollection.LowercaseUrls
Установите LowercaseUrls на true
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
...
}
Создать ссылку
@Html.ActionLink("Log in", "Login", "Account")
Это создаст удивительный, строчный url:)
<a href="/account/login">Log in</a>
Ответ 2
Для этого есть пакет NuGet: LowerCaseRoutesMVC (веб-сайт проекта)
Ответ 3
Если ваши причины для обеспечения строчной буквы - это просто SEO, то лучшим решением, которое я нашел, является использование IIS 7 URL Rewrite Module
У вас не только есть возможность принудительно вводить все url в строчные буквы, но также иметь доступ к правилам, которые позволяют вам удалять/добавлять конечные слэши, применять канонические домены и т.д.
Блог пользователя RuslanY имеет хороший набор для начала. Например, я использую следующие на всех моих сайтах:
<!-- http://ruslany.net/2009/04/10-url-rewriting-tips-and-tricks/ -->
<rule name="Convert to lower case" stopProcessing="true">
<match url=".*[A-Z].*" ignoreCase="false" />
<conditions>
<add input="{REQUEST_METHOD}" matchType="Pattern" pattern="GET" ignoreCase="false" />
</conditions>
<action type="Redirect" url="{ToLower:{R:0}}" redirectType="Permanent" />
</rule>
Вы просто добавляете вышеуказанные строки в раздел вашего web.config.
Ответ 4
Да, мне пришлось реализовать нечто подобное выше. Это, по-видимому, единственный способ сделать это.
Я хотел бы добавить, что кроме того мы добавили 301 переадресацию, так что любой трафик, исходящий из /Upper -Case-Url, будет 301 перенаправлен на/upper-case-url.
Ответ 5
Не уверен, что не так с вашим кодом (моя немного отличается, но по сути та же концепция). Он очень прост в реализации, и он полностью повторно используется.
LowerCaseRouteHelper.cs
using System.Web.Routing;
using System.Web.Mvc;
namespace Utilities.Helpers
{
public class LowercaseRouteHelper : System.Web.Routing.Route
{
public LowercaseRouteHelper(string url, IRouteHandler routeHandler) : base(url, routeHandler)
{
}
public LowercaseRouteHelper(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(url, defaults, routeHandler)
{
}
public LowercaseRouteHelper(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base(url, defaults, constraints, routeHandler)
{
}
public LowercaseRouteHelper(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;
}
}
public static class RouteCollectionExtensions
{
[System.Runtime.CompilerServices.Extension()]
public static void MapRouteLowercase(RouteCollection routes, string name, string url, object defaults)
{
routes.MapRouteLowercase(name, url, defaults, null);
}
[System.Runtime.CompilerServices.Extension()]
public static void MapRouteLowercase(RouteCollection routes, string name, string url, object defaults, object constraints)
{
if (routes == null) {
throw new ArgumentNullException("routes");
}
if (url == null) {
throw new ArgumentNullException("url");
}
object route = new LowercaseRouteHelper(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints)
};
if (String.IsNullOrEmpty(name)) {
routes.Add(route);
} else {
routes.Add(name, route);
}
}
}
}
глобальный
routes.MapRouteLowercase("Start", "", new {
controller = "Home",
action = "Index"
})
Мне это нравится, и великая вещь (как говорят комментарии) заключается в том, что она действительно помогает улучшить SEO.
Ответ 6
Лол, вы, ребята, слишком много делаете для себя. Просто добавьте это в свой global.asax application_beginrequest...
protected void Application_BeginRequest(Object sender, EventArgs e) {
string url = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
if (Regex.IsMatch(url, @"[A-Z]")) {
PermanentRedirect(url.ToLower() + HttpContext.Current.Request.Url.Query);
}
private void PermanentRedirect(string url) {
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", url);
Response.End();
}