2013-02-28 14 views
5

Ja obecnie pracuje na asp.net mvc 4 wniosku i mam potrzebę poniższej rodzaju adresów URL:ASP.NET MVC 4 trasa login/akcja problem

adresy URL, które powinny być kierowane

  1. http://www.mysite.com/foo/user1 < ------- {nazwa}
  2. http://www.mysite.com/foo/edit
  3. http://www.mysite.com/foo/delete/1
  4. http://www.mysite.com/bar/user1 < ------- {username}
  5. http://www.mysite.com/bar/edit
  6. http://www.mysite.com/bar/delete/1

Problem mam jest to, że obecnie {username} dostaje traktowane jako działanie tak obejść problem zaimplementowałem następujące trasy, ale to oznaczałoby, że za każdym razem, gdy chcę zaimplementować nową akcję lub kontroler, który potrzebuje {username}, musiałbym zaktualizować moje trasy:

tylko trasy Foo pokazano

routes.MapRoute("FooSomeAction", "foo/someaction", new { controller = "Food", action = "SomeAction" });    
routes.MapRoute("FooDelete", "foo/delete/{id}", new { controller = "Food", action = "Delete" });    


routes.MapRoute(
    "FooProfile", 
    "foo/{username}", 
    new { controller = "Foo", action = "Index", username = "" } 
); 


// Default route 
routes.MapRoute(
    "Default", // Route name 
    "{controller}/{action}/{id}", 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 

2 pytania

1) Czy istnieje jakiś sposób mogę osiągnąć powyższe adresy URL bez hardcoding wszystkie szlaki?

2) Jaki jest najlepszy sposób radzenia sobie z sytuacją, w której ktoś używa nazwy użytkownika, która ma taką samą nazwę jak kontroler lub nazwa działania?

DotnetShadow

+0

Twoje drugie pytanie, o ile wiem, nie jest możliwe. Co jest złego w tym, że tam też jest akcja? – mattytommo

+0

Co jest złego w tym, że tam też jest akcja? - Przepraszam, Co miałeś na myśli przez to? – DotnetShadow

+0

Przepraszam, jeśli byłem niejasny, mam na myśli to, że możliwe jest, że nazwa działania i kontrolera będą obecne w linku? Coś jak/User/Edit/User1? – mattytommo

Odpowiedz

3

Można by utworzyć ograniczenie niestandardowych trasach, które sprawdzić, czy nazwa użytkownika istnieje w możliwych działań na kontrolerze. Jeśli znajdzie dopasowanie akcji, nie powiedzie się i użyje domyślnej trasy (np. Edycja). Możesz chcieć buforować listę ze względu na wydajność, ale pozostawiam to tobie.

private static List<Type> GetSubClasses<T>() 
    { 
     return Assembly.GetCallingAssembly().GetTypes().Where(
      type => type.IsSubclassOf(typeof(T))).ToList(); 
    } 

    public static List<string> GetActionNames(string controllerName) 
    { 
     controllerName = controllerName + "Controller"; 
     var controller = GetSubClasses<Controller>().FirstOrDefault(c => c.Name == controllerName); 

     var names = new List<string>(); 
     if (controller != null) 
     { 
      var methods = controller.GetMethods(BindingFlags.Public | BindingFlags.Instance); 
      foreach (var info in methods) 
      { 
       if (info.ReturnType == typeof(ActionResult)) 
       { 
        names.Add(info.Name); 
       } 
      } 

     } 
     return names; 
    } 


    public class UsernameNotAction : IRouteConstraint 
    { 
     public bool Match 
      (
       HttpContextBase httpContext, 
       Route route, 
       string parameterName, 
       RouteValueDictionary values, 
       RouteDirection routeDirection 
      ) 
     { 
      int i = 0; 
      var username = values["username"]; 
      var actionList = GetActionNames(values["controller"].ToString()); 

      return !actionList.Any(a => a.ToUpper() == username.ToString().ToUpper()); 
     } 
    } 


    public static void RegisterRoutes(RouteCollection routes) 
    { 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     routes.MapRoute(
      "FooProfile", 
      "{controller}/{username}", 
      new { controller = "Home", action = "Index2", username = "" }, 
      new { IsParameterAction = new UsernameNotAction() } 
     ); 
     // Default route 
     routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 
    } 
+0

To bardzo interesujące rozwiązanie. Zdecydowanie nie chcesz wykonywać wywołań bazy danych za każdym razem, gdy nawigujesz, ale może on przechowywać listę nazw użytkowników w sesji. Nie jestem pewien, czy mi się podoba, ale dam +1 za oryginalność i świetny pomysł. –

+0

Good Stuff Mark, tak naprawdę myślałem o jakimś przymusie, ale też martwiłem się o wydajność. Dzięki za alternatywne podejście – DotnetShadow

+0

To właściwie nie robi wywołania bazy danych - testuje, czy akcja jest w kontrolerze za pomocą odbicia (może faktycznie być gorsza dla wydajności, ale kto wie) –

1

Nie można tego zrobić, chyba że kieruje się każdą trasą i nie jest to najlepsza droga.

Co jest złego w tym, że zawiera nazwę akcji?

+0

Co jest złego w posiadaniu nazwy kontrolera w to? - Co przez to rozumiesz? – DotnetShadow

+0

mi chodziło Nazwa działania Robiąc http://www.mysite.com/bar/user1 To map do kontrolera: bar i działanie user1 Chciałeś trafić Kontroler: bar Działanie: Index ale nie tak działają linie MVC Musisz zrobić coś w stylu: http://www.mysite.com/bar/ActionName/user1 –

2

To nie jest odpowiedź, której szukasz, przepraszam.

1) Nie ma sposobu na wytyczenie trasy. Nic nie odróżnia tych tras od siebie, poza tym, co zrobiłeś. Muszę zakwestionować, dlaczego jest to konieczne, jestem pewien, że masz dobry powód, ale nie ma to dla mnie żadnego sensu. Wciąż używasz akcji Index, więc dlaczego nie po prostu/foo/index/username. Wszystko, co mogę wymyślić, to z jakiegoś powodu nie masz kontroli nad adresem URL.

2) Jeśli używasz domyślnej trasy, nie ma problemu. Z twoim routingiem, problemem. Jedyną realną opcją jest ustawienie słów kontrolera i akcji jako słów zarezerwowanych (uniemożliwienie tworzenia użytkowników za pomocą tych nazw użytkowników w bazie danych).

Niestety, nie mogłem ci pomóc.

+0

Dobra racja: 1) posiadanie indeksu jako akcji, po prostu wygląda czysto foo/username Domyślam się, że Zasadniczo mój pomysł polegał na tym, że gdybyś oglądał profil anyone publicznie, musiałbym: /profil/nazwa_użytkownika /znajomych/nazwa_użytkownika /galeria/nazwa ale jeśli jestem w moim profilu Chciałbym po prostu zrobić /profile/Edycja/1 /przyjaciół/lista /galeria/usuwać/1 If to ma sens? – DotnetShadow

+0

Dostaję to, co próbujesz zrobić, ale domyślnym routingiem, który działa na 83,57% wszystkich przypadków, jest kontroler/akcja/widok. Jeśli chcesz przełamać ten schemat, generujesz pracę dla siebie, więc zadaj sobie pytanie, czy jest to warte wysiłku w porównaniu do tego, co zyskujesz. IMO. –

+0

Użytkownicy nie powinni także poruszać się po Twojej witrynie, modyfikując adres URL, a te będą dostępne za pośrednictwem linków akcji i tak naprawdę, czy ktoś patrzy na adres URL lub dba o to, jak wygląda? http: // mysite/viewusers/index/bob1111 vs http: // mysite/viewusers/bob1111, kto naprawdę będzie się tym przejmować? :) –

Powiązane problemy