URL маршрутизации в нижний регистр, как? - PullRequest
9 голосов
/ 25 декабря 2011

Я разработал веб-приложение на asp.net mvc3, и теперь мне нужно сделать маршруты, в нижнем регистреПример:

 that's what i have:
 http://www.example.com/SubFolder/Category/Index => looks ugly :-)

 that's how i would like it:
 http://www.example.com/subfolder/category/index

Я нашел это сообщение:http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/

Мне действительно нужно использовать код внутри global.asax внизу страницы.

protected void Application_BeginRequest(Object sender, EventArgs e)   
{
    string lowercaseURL = (Request.Url.Scheme + "://" + 
    HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
    if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
    {
      lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;
      Response.Clear();
      Response.Status = "301 Moved Permanently";
      Response.AddHeader("Location", lowercaseURL);
      Response.End();
    }
}

Теперь вопрос:Когда он используется на dev-станции, он работает отлично, но когда я загружаю его, на производство он не работает.

На dev-станции он делает только публикацию, а на производстве - два:

POST - status: 301 Moved Permanently 
GET  - status: 200 OK

и меня вообще не перенаправляют на правильный маршрут.На станции разработчика это работает отлично.

Ответы [ 4 ]

4 голосов
/ 03 сентября 2013
protected void Application_BeginRequest(Object sender, EventArgs e)
{
    string lowercaseURL = (Request.Url.Scheme + 
    "://" +
    HttpContext.Current.Request.Url.Authority +
    HttpContext.Current.Request.Url.AbsolutePath);
    if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
    {
        System.Web.HttpContext.Current.Response.RedirectPermanent
        (
             lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query
        );
    }
}
2 голосов
/ 03 сентября 2013

Если это просто для SEO, самое простое решение, которое я бы использовал, - это использовать перезапись URL (при условии, что вы работаете на IIS) или перезапись мода (если вы размещаете на Apache), чтобы ввести URL-адреса в нижнем регистре и оставитьсообщений как они есть.

С IIS это так же просто, как установить перезапись URL-адреса из установщика веб-платформы, нажать добавить правило и выбрать «принудительное использование строчных URL-адресов».Легко.

Если вы обновляетесь до mvc4 и действительно хотите писать в нижнем регистре, есть свойство LowercaseUrls, которое вы можете установить в true при регистрации маршрутов.Но опять же - я бы не стал беспокоиться.

2 голосов
/ 03 сентября 2013

Поскольку вы используете ASP.NET MVC, я не думаю, что Application_BeginRequest - это правильный путь. MVC предоставляет гораздо лучшие варианты для удовлетворения таких требований.

Этого также можно добиться с помощью модуля IIS Url Rewrite (с конфигурацией Web.config), но я предполагаю, что вы предпочитаете более программный подход.

Попробуйте вместо ActionFilter:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class EnforceLowercaseUrlAttribute : ActionFilterAttribute
{
    private bool _redirect;

    public EnforceLowercaseUrlAttribute(bool redirect = true)
    {
        this._redirect = redirect;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var path = request.Url.AbsolutePath;
        var containsUpperCase = path.Any(char.IsUpper);

        if (!containsUpperCase || request.HttpMethod.ToUpper() != "GET")
            return;

        if (this._redirect)
            filterContext.Result = new RedirectResult(path.ToLowerInvariant(), true);

        filterContext.Result = new HttpNotFoundResult();
    }
}

Затем примените его к контроллеру / действию:

[EnforceLowercaseUrl]
public ActionResult Index()
{
     ....
}

или зарегистрируйте глобально в вашем Global.asax:

GlobalFilters.Filters.Add(new EnforceLowercaseUrlAttribute());
0 голосов
/ 03 сентября 2013

Вот как я это делаю, я создаю собственный маршрут.Это также заставляет помощников, таких как Html.ActionLink, создавать также управляемые маршруты.

Сначала я расширяю Route пользовательским объектом (скажем, LowerCaseRoute) и переопределяю метод GetVirtualPath следующим образом:

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
    var path = base.GetVirtualPath(requestContext, values);
    if (path != null)
    {
        // you could do lots more here, like replacing odd characters with - etc.
        path.VirtualPath = path.VirtualPath.ToLower();
    }
    return path;
}

Затем я создаю настраиваемого помощника для сопоставления этого маршрута следующим образом:

public static LowerCaseRoute MapLowerCaseRoute(this RouteCollection routes, string name, string url, object defaults)
{
    var route = new LowerCaseRoute(url, new MvcRouteHandler());
    route.Defaults = new RouteValueDictionary(defaults);
    route.DataTokens = new RouteValueDictionary();
    route.DataTokens.Add("RouteName", name);
    routes.Add(name, route);
    return route;
}

Таким образом, вы можете создать маршрут в вашем global.asax следующим образом:

RouteTable.Routes.MapLowerCaseRoute("routeName", "baseurl/someother/{param}", { controller = "Controller", param = UrlParameter.Optional });

Это сохраняет все аккуратным и очевидным внутри проекта и дает вам больше возможностей для манипулирования вашими маршрутами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...