我正在尝试确保用于访问我的ASP.NET MVC站点的所有URL都是小写的。如果URL中包含大写字母,我将状态代码更改为301,并使用以下代码将位置更改为URL的小写版本:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var url = Request.Url.ToString();
if (Regex.IsMatch(url, @"[A-Z]"))
{
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
Response.AddHeader("Location", url.ToLower());
Response.End();
}
}
然而,最近一位同事试图将表单发布到带有大写字母的URL(忘记重定向),但是操作(标有HttpPost属性)没有被命中。查看Firebug中的请求显示了原始POST,但随后它返回301并向小写版本发出了GET。
我猜最好的解决方案就是确保所有的POST都是URL的小写版本,但我来到这里是为了看看是否有另一种方法来处理这个问题
答案 0 :(得分:3)
您可以为路由创建一个扩展方法,该方法将呈现所有网址的小写:
守则:
public class LowercaseRoute : System.Web.Routing.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 void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults)
{
routes.MapRouteLowercase(name, url, defaults, null);
}
public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, object constraints)
{
Check.Argument.IsNotNull(routes, "routs");
Check.Argument.IsNotNull(url, "url");
var route = new LowercaseRoute(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(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
现在,当您使用... Html.BeginForm()...时,它将呈现操作的小写URL。每当您使用路由来呈现链接时,这也将始终呈现小写URL,即Url.Action(); <%:Html.RenderAction()%>
答案 1 :(得分:1)
正如朱塞佩指出的那样,搜索引擎不会对POST页面进行索引。我最终得到了这个:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(Request.HttpMethod == "POST") return;
//etc
}
答案 2 :(得分:1)
这是一个基于scottm解决方案的版本,适用于.NET 4.0
protected void Application_BeginRequest(object sender, EventArgs e) {
string url = Request.Url.ToString();
if (Request.HttpMethod == "GET" && Regex.Match(url, "[A-Z]").Success) {
Response.RedirectPermanent(url.ToLower(), true);
}
}
答案 3 :(得分:0)
根据我的理解,没有办法强制用户重新发出POST请求。您只能重定向它们,并且这样做只会指定一个URL(而不是POST数据)。
对我来说,更大的问题是:为什么你如此坚持不拥有大写的URL? HTTP指定URLS不区分大小写。
答案 4 :(得分:0)
扩展@bingles很棒的答案,也许你不想强制GET数据小写?然后,您可能希望使用正则表达式(?<=^[^?]*)[A-Z]
:
protected void Application_BeginRequest(object sender, EventArgs e)
{
string url = Request.Url.ToString();
if (Request.HttpMethod == "GET" && Regex.Match(url, "(?<=^[^?]*)[A-Z]").Success)
{
Response.RedirectPermanent(url.ToLower(), true);
}
}
正则表达式取自另一个答案:regex to match all uppercase letters before the first question mark