Ответ 1
В классе RouteCollection теперь есть логическое выражение AppendTrailingSlash, для которого вы можете установить значение true.
У меня здесь небольшая проблема. Мне нужно добавить конечную косую черту в конце каждого 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.
Итак, что вы скажете, ребята?
В классе RouteCollection теперь есть логическое выражение AppendTrailingSlash, для которого вы можете установить значение true.
Вы можете создать новый маршрут, который переопределяет метод 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);
}
}
Хорошее чистое решение, 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;
}
Вышеупомянутое решение 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 с помощью механизма маршрутизации.
Я знаю, что есть более верные ответы, но лучший проголосовавший ответ не помог мне. Мне нужно сказать, что я нашел гораздо более легкое решение.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/", <-- trailing slash here
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Это будет действовать как косая черта "/" во всех случаях.
Есть несколько действительно хороших ответов, но вот какой-то код MVC Controller, как я его реализую в очень простой get.
public ActionResult Orders()
{
if (!Request.Path.EndsWith("/"))
{
return RedirectPermanent(Request.Url.ToString() + "/");
}
return View();
}
Надеюсь, это поможет кому-то.