Подтвердить что ты не робот

Добавить конечную косую черту в конце каждого URL-адреса?

У меня здесь небольшая проблема. Мне нужно добавить конечную косую черту в конце каждого URL-адреса на сайте, над которым я работаю. Я определил все ссылки внутри сайта, чтобы иметь завершающую косую черту:

<a href="/register/">Register</a>

Хотя это прекрасно работает, есть еще одна крошечная проблема: она сгенерированными URL-адресами, которые поступают из вызова RedirectToAction(). Например:

return RedirectToAction("Register", "Users");

Приведёт к тому, что URL-адрес изменится на /register без косой черты. Я изменил свою систему маршрутизации так:

  routes.MapRoute("register",
                        "register/",
                        new {controller = "Users", action = "Register"}
            );

Тем не менее требуемая конечная косая черта не добавляется автоматически!

Я просмотрел этот question и этот question, но они совершенно разные, поскольку я не используя любые библиотеки перезаписи url, я просто использую asp.net mvc routing system.

Итак, что вы скажете, ребята?

4b9b3361

Ответ 1

В классе RouteCollection теперь есть логическое выражение AppendTrailingSlash, для которого вы можете установить значение true.

Ответ 2

Вы можете создать новый маршрут, который переопределяет метод GetVirtualPath. В этом методе вы добавляете конечную косую черту к VirtualPath. Вот так:

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
     VirtualPathData path = base.GetVirtualPath(requestContext, values);

     if (path != null)
         path.VirtualPath = path.VirtualPath + "/";
     return path;
}

Для краткости я разместил весь пример на CodePaste.net

Теперь вам нужно только зарегистрировать маршруты с помощью routes.MapRouteTrailingSlash() вместо routes.MapRoute().

routes.MapRouteTrailingSlash("register",
                             "register",
                             new {controller = "Users", action = "Register"}
);

Затем маршрут добавит косую черту к пути при вызове GetVirtualPath(). Какой RedirectToAction() будет делать.

Обновление: Поскольку ссылка CodePaste не работает, вот полный код:

public class TrailingSlashRoute : Route {
    public TrailingSlashRoute(string url, IRouteHandler routeHandler)
        : base(url, routeHandler) {}

    public TrailingSlashRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
        : base(url, defaults, routeHandler) {}

    public TrailingSlashRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
                          IRouteHandler routeHandler)
        : base(url, defaults, constraints, routeHandler) {}

    public TrailingSlashRoute(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 + "/";
        return path;
    }
}

public static class RouteCollectionExtensions {
    public static void MapRouteTrailingSlash(this RouteCollection routes, string name, string url, object defaults) {
        routes.MapRouteTrailingSlash(name, url, defaults, null);
    }

    public static void MapRouteTrailingSlash(this RouteCollection routes, string name, string url, object defaults,
                                         object constraints) {
        if (routes == null)
            throw new ArgumentNullException("routes");

        if (url == null)
            throw new ArgumentNullException("url");

        var route = new TrailingSlashRoute(url, new MvcRouteHandler())
                    {
                        Defaults = new RouteValueDictionary(defaults),
                        Constraints = new RouteValueDictionary(constraints)
                    };

        if (String.IsNullOrEmpty(name))
            routes.Add(route);
        else
            routes.Add(name, route);
    }
}

Ответ 3

Хорошее чистое решение, codingbug!

Единственной проблемой, с которой я столкнулся, была двойная косая черта для главной страницы MVC3.

Пример бритвы:

@Html.ActionLink("Home", "Index", "Home")

Ссылка на:
http://mysite.com//

Чтобы исправить это, я изменил переопределение GetVirtualPath:

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{       
    VirtualPathData path = base.GetVirtualPath(requestContext, values);       

    if (path != null && path.VirtualPath != "")       
        path.VirtualPath = path.VirtualPath + "/";       
    return path;       
}

Ответ 4

Вышеупомянутое решение codingbug очень приятно. Мне нужно было что-то очень симулятивное, но только для моего корневого URL. Я знаю, что с этим возникают проблемы, но вот что я сделал. Кажется, это прекрасно работает во всех моих условиях. Я думаю, что это тоже работает, потому что это только наша домашняя страница, когда они впервые приходят и у меня нет тренировочной косой черты. Это тот случай, который я пытался избежать. Если это то, чего вы хотите избежать, это будет работать для вас.

  public class HomeController : Controller
  {
    public ActionResult Index()
    {
      if (!Request.RawUrl.Contains("Index") && !Request.RawUrl.EndsWith("/"))
        return RedirectToAction("Index", "Home", new { Area = "" });

Если окажется, мне нужно больше загара. Я, вероятно, буду использовать код, предоставленный codingbug. До тех пор мне нравится держать его простым.

Примечание. Я рассчитываю, что Home\Index будет удален из URL с помощью механизма маршрутизации.

Ответ 5

Я знаю, что есть более верные ответы, но лучший проголосовавший ответ не помог мне. Мне нужно сказать, что я нашел гораздо более легкое решение.

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}/", <-- trailing slash here
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

Это будет действовать как косая черта "/" во всех случаях.

Ответ 6

Есть несколько действительно хороших ответов, но вот какой-то код MVC Controller, как я его реализую в очень простой get.

    public ActionResult Orders()
    {
        if (!Request.Path.EndsWith("/"))
        {
            return RedirectPermanent(Request.Url.ToString() + "/");
        }
        return View();
    }

Надеюсь, это поможет кому-то.