2010-06-23 11 views
5

Próbuję utworzyć identyfikatory URI, które wyglądają trochę mniej więcej tak: http://hostname/mobile/en/controller/action dla telefonów komórkowych LUB http://hostname/en/controller/action dla komputerów stacjonarnych (inne niż telefony komórkowe).Trasa zawsze przechodzi do pierwszego maproute

stół

My Route obecnie wygląda następująco (Global.asax.cs)

 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     routes.MapRoute(
      "Mobile", // Route name 
      "mobile/{language}/{controller}/{action}/{id}", // URL with parameters 
      new { language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
      new { language = @"en|us" } // validation 
     ); 
     routes.MapRoute(
      "Default", // Route name 
      "{language}/{controller}/{action}/{id}", // URL with parameters 
      new { language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
      new { language = @"en|us" } // validation 
     ); 

Problem pojawia się, gdy próbuję zrobić return RedirectToAction("Add", "User"); To zawsze przekierowuje przeglądarkę na pulpicie z /en/User/List do /mobile/en/User/Add kiedy chcę to przejść do /en/User/Add. Wersja mobilna działa poprawnie, ale uważam, że dzieje się tak dlatego, że pierwsza "mobilna" trasa zawsze była postrzegana jako trasa, która pasuje, nawet jeśli nie ma/mobilnego/na starcie.

Próbuję użyć tego samego Controller dla obu wersji, ale jestem zatrzymany na zawsze przekierowanie do Telefony trasie. Oznacza to, że RedirectToRoute nie jest idealny, ponieważ chcę dynamicznych tras.

Dzięki za pomoc.

Odpowiedz

2

Głównym problemem jest to, że podane przez ciebie trasy-trasy pasują do obu tras, co oznacza, że ​​zajmie pierwszą (która jest mobilna).

Możesz ręcznie wybrać trasę do wykorzystania, przekierowując na trasy zamiast działań.

return RedirectToRoute("Mobile", new { 
    language = "en", controller = "User", action = "Get", id = 20 
}); 

na telefon komórkowy lub

return RedirectToRoute("Default", new { 
    language = "en", controller = "User", action = "Get", id = 20 
}); 

dla domyślnej trasy.

To jednak powoduje nowy problem: uzyskanie nazwy bieżącej trasy. Jak widać w przykładzie, bardzo dobrym możliwym jest odwołanie się do nazwanych tras. Uzyskanie nazwy aktualnie używanej trasy wydaje się jednak niemożliwe. Używanie hakowania, jak patrzenie na aktualny URI, nie jest oczywiście pożądane. Poza tym, że jest brzydki (hack), może również prowadzić do wielu powielania kodu.

Istnieje jednak możliwość dodania wartości do tras, które można łatwo uzyskać z kontrolera (lub widoku):

routes.MapRoute(
    "Mobile", // Route name 
    "mobile/{language}/{controller}/{action}/{id}", // URL with parameters 
    new { routeName = "Mobile", language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
    new { language = @"en|us" } // validation 
); 
routes.MapRoute(
    "Default", // Route name 
    "{language}/{controller}/{action}/{id}", // URL with parameters 
    new { routeName = "Default", language = "en", controller = "Route", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
    new { language = @"en|us" } // validation 
); 

Teraz z kodu można przekierować do aktualnej trasy przy użyciu wartości pochodzić z samej trasie:

return RedirectToRoute(RouteData.Values["routeName"], new { 
    language = "en", controller = "User", action = "Get", id = 20 
}); 

teraz, jeśli chcesz, aby ten całkowicie fantazyjne, można nawet zrobić metodę rozszerzenia z tego:

public static class ControllerExtensions { 
    public static RedirectToRouteResult CustomRedirectToRoute(this Controller controller, string controllerName, string actionName, object routevalues) { 
     return CustomRedirectToRoute(controller, controllerName, actionName, new RouteValueDictionary(routevalues)); 
    } 

    public static RedirectToRouteResult CustomRedirectToRoute(this Controller controller, string controllerName, string actionName, RouteValueDictionary routevalues) { 
     routevalues = routevalues ?? new RouteValueDictionary(); 
     routevalues.Add("controller", controllerName); 
     routevalues.Add("action", actionName); 
     return new RedirectToRouteResult(controller.RouteData.Values["routeName"] as string, routevalues); 
    } 
} 

Mamy nadzieję, że to dobre rozwiązanie Twojego problemu!

+0

Dziękuję René, że wyglądają dokładnie tak, jak miałem nadzieję. Czy możesz mi powiedzieć, gdzie najlepiej jest umieścić metodę przedłużenia? – Adrian

+1

Umieść statyczne rozszerzenie ControllerExtensions gdziekolwiek chcesz. A w kontrolerze chciałbyś skorzystać z przekierowania, pamiętaj o włączeniu przestrzeni nazw, w której znajduje się klasa rozszerzeń. Następnie w dowolnym miejscu kontrolera możesz użyć this.CusomRedirectToRoute ("Home", "Index", routeValues); Możesz także dodać inną metodę rozszerzenia, która wstawi null jako wartość routeValues, jeśli chcesz. –

+0

Jeśli chcesz go posprzątać, ostatnia część mojego komentarza może zostać zastąpiona przez czysty i uporządkowany system uzyskiwania nazwy trasy opisanej w tym wpisie: http://stackoverflow.com/questions/363211/how -can-i-get-the-nazwa-trasy-w-kontrolerze-w-asp-net-mvc –

Powiązane problemy