在每个网址的末尾添加一个尾部斜杠?

时间:2009-09-06 09:09:20

标签: asp.net-mvc url-routing

我这里有点问题。我需要在我正在处理的网站的每个网址末尾添加一个尾部斜杠。我将网站内的所有链接定义为具有如下的尾部斜杠:

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

虽然这很好但仍有一个小问题:它来自调用RedirectToAction()的生成的url。例如:

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

将导致url更改为/ register而不使用尾部斜杠。我修改了我的路由系统:

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

仍然无法自动添加所需的尾部斜杠!
我查看了这个questionquestion,但这些完全不同,因为我没有使用任何url重写库,我只是使用asp.net mvc路由系统。
那么你们怎么说呢?

6 个答案:

答案 0 :(得分:47)

RouteCollection类现在有一个AppendTrailingSlash布尔值,您可以为此行为设置为true。

答案 1 :(得分:20)

您可以创建一个覆盖GetVirtualPath方法的新Route。在此方法中,您将向VirtualPath添加尾部斜杠。像这样:

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

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

为简洁起见,我发布了whole example on 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);
    }
}

答案 2 :(得分:5)

漂亮干净的解决方案,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;       
}

答案 3 :(得分:3)

通过codingbug的上述解决方案非常好。我需要一些非常相似的东西,但仅限于我的根URL。我知道这可能有问题,但这就是我所做的。它似乎在我的所有环境中都运行良好。我认为它也有效,因为它只是我们的主页,当他们刚来时并没有训练斜线。这是我试图避免的一个案例。如果这是你想要避免的,这对你有用。

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

如果事实证明我需要更多。我可能会使用codingbug提供的代码。在那之前,我喜欢保持简单。

注意:我指望路由引擎从URL中删除Home \ Index。

答案 4 :(得分:1)

我知道有更多的赞成答案,但最好的投票答案对我的案子不起作用。需要我说我找到了一个更容易的解决方案。

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

这将作为尾随斜线&#34; /&#34;在所有情况下。

答案 5 :(得分:1)

有一些非常好的答案,但这里有一些MVC Controller代码,我是如何在一个非常简单的get中实现它的。

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

希望这有助于某人。