Add a trailing slash at the end of each url?

寵の児 提交于 2019-12-17 10:21:19

问题


I have a little problem here. I need to add a trailing slash at the end of each url in the site I'm working on. I defined all the links inside the site to have a trailing slash like so:

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

While this works fine there's still one tiny issue: it's with the generated urls that come from calling RedirectToAction(). For example:

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

Will cause the url to change to /register with no trailing slash. I modified my routing system as so:

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

Still the required trailing slash doesn't get added automatically!
I looked up this question and this question but these are totally different as I'm not using any url rewriting libraries, i'm just using asp.net mvc routing system.
So what do you say guys?


回答1:


The RouteCollection Class now has a AppendTrailingSlash boolean which you can set to true for this behavior.




回答2:


You can create a new Route which overrides the GetVirtualPath method. In this method you add a trailing slash to the VirtualPath. Like this:

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

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

For brevity I posted the whole example on CodePaste.net

Now all you have to do is register the routes with routes.MapRouteTrailingSlash() instead of routes.MapRoute().

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

The route will then add a slash to the path when the GetVirtualPath() is called. Which RedirectToAction() will do.

Update: Because the CodePaste link is down, here is the full code:

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:


Nice clean solution, codingbug!!

Only problem I ran into was double trailing slashes for the home page in MVC3.

Razor example:

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

Linked to:
http://mysite.com//

To fix this I tweaked the GetVirtualPath override:

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:


The above solution by codingbug is very nice. I needed something very similar, but only for my root URL. I know there are possible problems with this, but here is what I did. It seems to work just fine in all of my environments. I think it works too, because it is only our Home page when they first come and do not have the training slash. That is the one case I was trying to avoid. If that is what you want to avoid, this will work for you.

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

If it turns out I need more than this. I will probably use code that codingbug provided. Until then, I like to keep it simple.

Note: I am counting on Home\Index to be removed from the URL by the routing engine.




回答5:


I know there are more upvoted answers, but the best voted answer didn't work for my case. Need I say that I found a far easier solution.

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

This will act as trailing slash "/" in all the cases.




回答6:


There are some really good answers but here is some MVC Controller code of how I implement it in a very simple get.

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

Hope this helps someone.



来源:https://stackoverflow.com/questions/1385265/add-a-trailing-slash-at-the-end-of-each-url

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!