web-dev-qa-db-ja.com

各URLの最後にスラッシュを追加しますか?

ここで少し問題があります。作業中のサイトの各URLの最後にスラッシュを追加する必要があります。サイト内のすべてのリンクを次のように末尾にスラッシュを付けるように定義しました。

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

これは正常に機能しますが、まだ1つの小さな問題があります。それは、RedirectToAction()の呼び出しから生成されたURLにあります。例えば:

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

URLが/ registerに変更され、末尾にスラッシュは表示されません。ルーティングシステムを次のように変更しました。

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

それでも、必要な末尾のスラッシュは自動的に追加されません。
これを調べました 質問 とこれ 質問 しかし、URL書き換えライブラリを使用しておらず、aspを使用しているだけなので、これらはまったく異なります。ネットMVCルーティングシステム。
では、皆さんは何と言いますか?

30
Galilyou

RouteCollectionクラスにAppendTrailingSlashブール値が追加され、この動作に対してtrueに設定できるようになりました。

48
Schmidty

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);
    }
}
_
20
aolde

素敵なクリーンソリューション、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;       
}
5
Akaoni

コーディングバグによる上記の解決策は非常に素晴らしいです。非常によく似たものが必要でしたが、ルートURLのみが必要でした。これには問題がある可能性があることはわかっていますが、これが私がしたことです。私のすべての環境で問題なく動作しているようです。彼らが最初に来たときは私たちのホームページだけであり、トレーニングスラッシュがないので、それもうまくいくと思います。それは私が避けようとしていた1つのケースです。それがあなたが避けたいものであるならば、これはあなたのために働くでしょう。

  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が削除されることを期待しています。

3
Bobby Ortiz

いくつかの本当に良い答えがありますが、これは私が非常に単純なgetでそれを実装する方法のいくつかのMVCコントローラーコードです。

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

これが誰かを助けることを願っています。

1
Sustare

賛成の回答がもっとあることは知っていますが、私の場合、最高の回答はうまくいきませんでした。私ははるかに簡単な解決策を見つけたと言う必要があります。

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

これは、すべての場合で末尾のスラッシュ「/」として機能します。

1
radu florescu