Szukaj…


Wprowadzenie

Routing to sposób, w jaki ASP.NET MVC dopasowuje identyfikator URI do akcji. Moduł routingu jest odpowiedzialny za mapowanie przychodzących żądań przeglądarki na określone działania kontrolera MVC.

MVC 5 obsługuje nowy typ routingu, zwany routingiem atrybutów. Jak sama nazwa wskazuje, routing atrybutów używa atrybutów do definiowania tras. Routing atrybutów zapewnia większą kontrolę nad identyfikatorami URI w aplikacji internetowej.

Niestandardowe trasy

Niestandardowe routing zapewnia specjalną potrzebę routingu w celu obsługi określonych żądań przychodzących.

Aby zdefiniować trasy niestandardowe, należy pamiętać, że kolejność tras dodawanych do tabeli tras jest ważna.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    // this is an advanced custom route
    // you can define custom URL with custom parameter(s) point to certain action method
    routes.MapRoute(
    "CustomEntry", // Route name
    "Custom/{entryId}", // Route pattern
    new { controller = "Custom", action = "Entry" } // Default values for defined parameters above
    );

    // this is a basic custom route
    // any custom routes take place on top before default route
    routes.MapRoute(
    "CustomRoute", // Route name
    "Custom/{controller}/{action}/{id}", // Route pattern
    new { controller = "Custom", action = "Index", id = UrlParameter.Optional } // Default values for defined parameters above
    );

    routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // Route pattern
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Default values for defined parameters above
    );
}

nazwy controller i action są zastrzeżone. Domyślnie MVC mapuje {controller} część adresu URL do klasy <controller>Controller , a następnie szuka metody o nazwie <action> bez dodawania żadnych przyrostków.

Chociaż tworzenie rodziny tras przy użyciu szablonu {controller}/{action}/{parameter} może być kuszące, pamiętaj, że robiąc to, ujawniasz strukturę swojej aplikacji i sprawiasz, że adresy URL są nieco kruche, ponieważ zmiana nazwy kontrolera zmienia trasy i zrywa linki zapisane przez użytkownika.

Preferuj wyraźne ustawienie trasy:

routes.MapRoute(
    "CustomRoute", // Route name
    "Custom/Index/{id}", // Route pattern
    new { controller = "Custom", action = nameof(CustomController.Index), id = UrlParameter.Optional }
);

(nie można użyć operatora nameof do nazwy kontrolera, ponieważ będzie miał on dodatkowy przyrostek Controller ), którego należy pominąć przy ustawianiu nazwy kontrolera na trasie.

Dodawanie niestandardowej trasy w Mvc

Użytkownik może dodać niestandardową trasę, mapując adres URL do określonej akcji w kontrolerze. Służy to do optymalizacji pod kątem wyszukiwarek i sprawia, że adresy URL są czytelne.

routes.MapRoute(
  name: "AboutUsAspx", // Route name
  url: "AboutUs.aspx",  // URL with parameters
  defaults: new { controller = "Home", action = "AboutUs", id = UrlParameter.Optional }  // Parameter defaults
);

Routing atrybutów w MVC

Wraz z klasycznym sposobem definiowania trasy MVC WEB API 2, a następnie frameworki MVC 5 wprowadziły Attribute routing :

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
        // This enables attribute routing and must go  before other routes are added to the routing table.
        // This makes attribute routes have higher priority
        routes.MapMvcAttributeRoutes();  
    }
}

W przypadku tras z tym samym prefiksem w kontrolerze można ustawić wspólny prefiks dla całych metod akcji w kontrolerze za pomocą atrybutu RoutePrefix .

[RoutePrefix("Custom")]
public class CustomController : Controller
{
    [Route("Index")]
    public ActionResult Index()
    {
        ...
    }
}

RoutePrefix jest opcjonalny i definiuje część adresu URL, która jest poprzedzona wszystkimi działaniami kontrolera.

Jeśli masz wiele tras, możesz ustawić domyślną trasę przechwytując akcję jako parametr, a następnie zastosować ją do całego kontrolera, chyba że określony atrybut Route zdefiniowany w niektórych metodach działania zastępuje trasę domyślną.

[RoutePrefix("Custom")]
[Route("{action=index}")]
public class CustomController : Controller
{
    public ActionResult Index()
    {
        ...
    }

    public ActionResult Detail()
    {
        ...
    }
}

Podstawy routingu

Kiedy żądać url yourSite/Home/Index za pośrednictwem przeglądarki, moduł routingu skieruje wniosek do Index metody działaniem HomeController klasie. Skąd wiadomo, że wysyła żądanie do metody określonej klasy? nadchodzi tabela tras.

Każda aplikacja ma tablicę tras, w której przechowuje wzorzec trasy i informacje o tym, dokąd skierować żądanie. Dlatego podczas tworzenia aplikacji mvc istnieje już domyślna trasa zarejestrowana w tabeli routingu. Możesz to zobaczyć w klasie RouteConfig.cs .

public static void RegisterRoutes(RouteCollection routes)
{
   routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
   routes.MapRoute("Default", "{controller}/{action}/{id}",
             new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}

Widać, że wpis ma nazwę i szablon. Szablon to wzorzec trasy, który należy sprawdzić, gdy nadejdzie żądanie. Domyślny szablon ma wartość Home jako wartość segmentu adresu URL kontrolera i Index jako wartość dla segmentu akcji. Oznacza to, że jeśli nie podasz jawnie nazwy kontrolera i akcji w swoim żądaniu, użyje tych wartości domyślnych. Jest to powód, dla którego uzyskujesz ten sam wynik, kiedy uzyskujesz dostęp do yourSite/Home/Index i yourSite

Być może zauważyłeś, że mamy parametr o nazwie id jako ostatni segment naszego wzorca trasy. Ale domyślnie określamy, że jest opcjonalny. To dlatego nie musieliśmy określać wartości identyfikatora w adresie URL, którego próbowaliśmy.

Teraz wróć do metody akcji Indeks w HomeController i dodaj do niej parametr

public ActionResult Index(int id)
{
     return View();
}

Teraz w tej metodzie umieść punkt przerwania studia wizualnego. Uruchom swój projekt i yourSite/Home/Index/999 dostęp do yourSite/Home/Index/999 w przeglądarce. Punkt przerwania zostanie trafiony i powinieneś zobaczyć, że wartość 999 jest teraz dostępna w parametrze id .

Tworzenie drugiego wzorca trasy

Powiedzmy, że chcielibyśmy ustawić go tak, aby ta sama metoda akcji została wywołana dla innego wzorca trasy. Możemy to zrobić, dodając nową definicję trasy do tabeli tras.

public static void RegisterRoutes(RouteCollection routes)
{
   routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
   
   // New custom route definition added
   routes.MapRoute("MySpecificRoute",
    "Important/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional });

   //Default catch all normal route definition
   routes.MapRoute("Default", "{controller}/{action}/{id}",
             new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}

Nowa definicja, którą dodałem, ma wzór Important/{id} gdzie id jest ponownie opcjonalny. Oznacza to, że kiedy yourSiteName\Important o yourSiteName\Important lub yourSiteName\Important\888 , zostanie ona wysłana do akcji indeksu HomeController.

Kolejność rejestracji definicji trasy

Ważna jest kolejność rejestracji trasy. Zawsze należy zarejestrować określone wzorce tras przed ogólną domyślną trasą.

Trasa catch-all

Załóżmy, że chcemy mieć trasę, która pozwala na nieograniczoną liczbę segmentów:

Musielibyśmy dodać trasę, zwykle na końcu tabeli tras, ponieważ prawdopodobnie przechwyciłaby ona wszystkie żądania, w ten sposób:

routes.MapRoute("Final", "Route/{*segments}",
      new { controller = "Product", action = "View" });

W kontrolerze działaniem, które mogłoby to obsłużyć, może być:

public void ActionResult View(string[] segments /* <- the name of the parameter must match the name of the route parameter */)
{
    // use the segments to obtain information about the product or category and produce data to the user
    // ...
}

Trasa typu catch-all umożliwiająca routing po stronie klienta

Dobrą praktyką jest kodowanie stanu aplikacji pojedynczej strony (SPA) w adresie URL:

my-app.com/admin-spa/users/edit/id123

Umożliwia to zapisywanie i udostępnianie stanu aplikacji.
Gdy użytkownik umieści adres URL w pasku adresu przeglądarki i trafi, wejdź na serwer, musisz zignorować część żądanego adresu URL po stronie klienta. Jeśli podasz swój SPA jako renderowany widok Razor (wynik działania kontrolera wywołującego) zamiast statycznego pliku HTML, możesz użyć trasy catch-all:

public class AdminSpaController
{
    [Route("~/admin-spa/{clienSidePart*}")]
    ActionResult AdminSpa()
    {
        ...
    }
}

W tym przypadku serwer zwraca tylko SPA, a następnie inicjuje się zgodnie z trasą. To podejście jest bardziej elastyczne, ponieważ nie zależy od modułu przepisywania adresu URL .

Trasowanie atrybutów w obszarach

Aby korzystać z routingu atrybutów w obszarach, wymagana jest rejestracja obszarów i [RouteArea(...)] .

W RouteConfig.cs :

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapMvcAttributeRoutes();
        AreaRegistration.RegisterAllAreas();
    }
}

W przykładowej definicji routingu atrybutów kontrolera obszaru:

[RouteArea("AreaName", AreaPrefix = "AreaName")]
[RoutePrefix("SampleAreaController")]
public class SampleAreaController : Controller
{
    [Route("Index")]
    public ActionResult Index()
    {
        return View();
    }
}

Aby użyć linków Url.Action w obszarach:

@Url.Action("Index", "SampleAreaController", new { area = "AreaName" })


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow