Как мне обеспечить строчные URL на POST? - PullRequest
1 голос
/ 03 декабря 2010

Я стараюсь, чтобы все URL-адреса, используемые для доступа к моему сайту ASP.NET MVC, были строчными.Если в 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, но я пришел сюда, чтобы посмотреть, есть ли другой способ решить эту проблему

Ответы [ 5 ]

3 голосов
/ 04 декабря 2010

Вы можете создать метод расширения для маршрутизации, который будет отображать все строчные буквы URL:

Код:

 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 голос
/ 26 марта 2011

Вот версия, основанная на решении Скотта, которое работает с .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);
    }
}
1 голос
/ 04 декабря 2010

Как отметил Джузеппе, поисковые системы не индексируют страницы POST. Я закончил с этим:

protected void Application_BeginRequest(object sender, EventArgs e)
{
  if(Request.HttpMethod == "POST") return;

  //etc
}
0 голосов
/ 07 февраля 2014

Расширяя @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);
    }
}

Регулярное выражение, взятое из этого другого ответа: регулярное выражение для сопоставления всех заглавных букв перед первым знаком вопроса

0 голосов
/ 03 декабря 2010

Насколько я понимаю, нет способа заставить пользователя повторить запрос POST. Вы можете только перенаправить их, и при этом указывается только URL (не данные POST).

Большой вопрос для меня: почему вы так непреклонны в отношении отсутствия прописных URL-адресов? HTTP указывает, что URL-адреса нечувствительны к регистру.

...