是否有任何简单/内置的方法可以为MVC3制作小写的URL。
我有代码可以做到,但看起来很容易实现。
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;
}
}
答案 0 :(得分:99)
我刚刚注意到.NET Framework 4.5中有一个新属性。效果很好! RouteCollection.LowercaseUrls
将LowercaseUrls设置为true
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
...
}
创建链接
@Html.ActionLink("Log in", "Login", "Account")
这将创建令人敬畏的小写网址:)
<a href="/account/login">Log in</a>
答案 1 :(得分:17)
有一个NuGet包:LowerCaseRoutesMVC(Project website)
答案 2 :(得分:12)
如果您强制执行小写的原因纯粹是SEO,那么我找到的最佳解决方案是使用IIS 7 URL Rewrite Module
您不仅可以将所有网址强制为小写,而且还可以访问允许您删除/添加尾部斜杠的规则,强制执行规范域等。
RuslanY's Blog有一个良好的开端。例如,我在所有网站上使用以下内容:
<!-- 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的部分。
答案 3 :(得分:1)
是的,我必须实施与上述类似的东西。它似乎是实现这一目标的唯一顺利方式。
我想补充一点,此外,我们添加了301重定向,以便来自/ Upper-Case-Url的任何流量都将被重定向到/ upper-case-url。
答案 4 :(得分:1)
不确定你的代码有什么问题(我的代码有点不同,但基本上是相同的概念)。它实现起来非常简单,而且完全可以重用。
<强> 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。
答案 5 :(得分:0)
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();
}