2009-09-06 25 views
28

Mam tu mały problem. Muszę dodać końcowy ukośnik na końcu każdego adresu URL w witrynie, nad którą pracuję. I zdefiniowane wszystkie linki wewnątrz witryny mieć ukośnik tak:
Dodaj końcowy ukośnik na końcu każdego adresu URL?

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

Chociaż to działa prawidłowo jest jeszcze jeden mały problem: to z generowanych adresów URL, które pochodzą z wywołaniem RedirectToAction(). Na przykład:

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

spowoduje url, aby zmienić/zarejestrować bez końcowy ukośnik. I zmodyfikowane mój system routingu jak tak:

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

Wciąż wymaganej spływu ukośnik nie dodawane automatycznie!
Sprawdziłem to question i ten question, ale są one całkowicie różne, ponieważ nie używam żadnych bibliotek przepisywania URL, po prostu używam systemu routingu mvc asp.net.
Co powiesz na facetów?

+0

Dla wszystkich zainteresowanych o tym, jak to zrobić dla ASP.NET Rdzenia użyć 'services.Configure (routeOptions => {routeOptions.AppendTrailingSlash = true;};' 'usługi obsługi gdzie jest' IServiceCollection' – Galilyou

Odpowiedz

46

Klasa RouteCollection ma teraz wartość boolowską AppendTrailingSlash, którą można ustawić na true dla tego zachowania.

+0

Wielkie dzięki. To najlepsze rozwiązanie dla mnie. – Stuart

+1

Oznacz tę odpowiedź jako poprawną, proszę –

+0

Nie, nie działa z MVC4. – RoninCoder

21

Możesz utworzyć nową trasę, która zastępuje metodę GetVirtualPath. W tej metodzie dodajesz ukośny ukośnik do VirtualPath. Tak:

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

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

Dla zwięzłości ja wysłana whole example on CodePaste.net

Teraz wszystko co musisz zrobić, to zarejestrować trasy z routes.MapRouteTrailingSlash() zamiast routes.MapRoute().

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

Trasa następnie doda ukośnik do ścieżki po wywołaniu GetVirtualPath(). Co zrobi RedirectToAction().

Aktualizacja: Ponieważ link CodePaste jest w dół, tutaj jest pełny kod:

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); 
    } 
} 
+0

Dzięki Manticore , to sprawdzi ... – Galilyou

+0

CodePaste.net Złamany link – John

+0

Bardzo chciałbym zobaczyć cały przykładowy kod, o którym wspomniałeś. Niestety twój link jest zepsuty :(Czy jest szansa, że ​​podasz alternatywny link, więc mogę zobaczyć twój przykładowy kod, proszę? – marcusstarnes

5

Nice clean rozwiązanie, codingbug !!

Jedyny problem, na który natrafiłem, to podwójne ukośne ukośniki dla strony głównej w MVC3.

Razor przykład:

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

Związany z:
http://mysite.com//

Aby rozwiązać ten problem I manipulowane nadpisanie 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

Powyższe rozwiązanie przez codingbug jest bardzo miłe. Potrzebowałem czegoś bardzo podobnego, ale tylko dla mojego głównego adresu URL. Wiem, że są z tym problemy, ale oto, co zrobiłem. Wydaje się, że działa dobrze we wszystkich moich środowiskach. Myślę, że to też działa, ponieważ jest to tylko nasza strona główna, kiedy przychodzą po raz pierwszy i nie mają treningu. To jedyny przypadek, którego próbowałem uniknąć. Jeśli tego właśnie chcesz uniknąć, zadziała to dla Ciebie.

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

Jeśli się okaże, że potrzebuję więcej opalenizny. Prawdopodobnie użyję kodu dostarczonego przez kodowanie. Do tego czasu lubię to utrzymywać.

Uwaga: Liczę na to, że Home \ Index zostanie usunięty z adresu URL przez silnik routingu.

1

Wiem, że jest więcej głosów przegłosowanych, ale najlepsza głosowana odpowiedź nie zadziałała w moim przypadku. Czy muszę powiedzieć, że znalazłem o wiele łatwiejsze rozwiązanie.

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

Będzie to działało jako ukośnik "/" we wszystkich przypadkach.

+1

Nie, nie będzie. Jeśli zrobisz to w ten sposób, a następnie wygenerujesz adres URL za pomocą RouteUrl ("{nazwa trasy"}, new RouteValueDictionary ({parametry})), końcowe ukośniki zostaną odcięte. – Przemo

0

Istnieje kilka naprawdę dobrych odpowiedzi, ale tutaj jest jakiś kod kontrolera MVC, jak go wdrożyć w bardzo prosty sposób.

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

Mam nadzieję, że to komuś pomaga.

Powiązane problemy