asp.net-mvc
Routing
Suche…
Einführung
Beim Routing wird in ASP.NET MVC ein URI einer Aktion zugeordnet. Das Routing-Modul ist dafür verantwortlich, eingehende Browseranforderungen bestimmten MVC-Controller-Aktionen zuzuordnen.
MVC 5 unterstützt einen neuen Routing-Typ, der als Attribut-Routing bezeichnet wird. Wie der Name schon sagt, verwendet Attributrouting Attribute, um Routen zu definieren. Das Attribut-Routing gibt Ihnen mehr Kontrolle über die URIs in Ihrer Webanwendung.
Benutzerdefiniertes Routing
Benutzerdefiniertes Routing bietet spezielle Anforderungen an das Routing, um bestimmte eingehende Anforderungen zu bearbeiten.
Beachten Sie bei der Definition von benutzerdefinierten Routen, dass die Reihenfolge der Routen, die Sie der Routentabelle hinzufügen, wichtig ist.
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
);
}
controller
und action
sind reserviert. Standardmäßig ordnet MVC {controller}
Teil der URL der Klasse <controller>Controller
und sucht dann nach einer Methode mit dem Namen <action>
ohne Suffixe hinzuzufügen.
Obwohl es verlockend sein kann, eine Routenfamilie mithilfe der Vorlage {controller}/{action}/{parameter}
zu erstellen, sollten Sie dabei die Struktur Ihrer Anwendung offenlegen und die URLs etwas spröde machen, da sich der Name des Controllers ändert Routen und bricht die vom Benutzer gespeicherten Links.
Bevorzugen Sie die explizite Routeneinstellung:
routes.MapRoute(
"CustomRoute", // Route name
"Custom/Index/{id}", // Route pattern
new { controller = "Custom", action = nameof(CustomController.Index), id = UrlParameter.Optional }
);
(Der nameof
Operators kann nicht für den Controller-Namen verwendet werden, da er ein zusätzliches Suffix Controller
), der beim Festlegen des Controller-Namens in der Route weggelassen werden muss.
Hinzufügen einer benutzerdefinierten Route in Mvc
Der Benutzer kann eine benutzerdefinierte Route hinzufügen und eine URL einer bestimmten Aktion in einem Controller zuordnen. Dies wird zum Zweck der Suchmaschinenoptimierung verwendet und macht URLs lesbar.
routes.MapRoute(
name: "AboutUsAspx", // Route name
url: "AboutUs.aspx", // URL with parameters
defaults: new { controller = "Home", action = "AboutUs", id = UrlParameter.Optional } // Parameter defaults
);
Attributrouting in MVC
Neben der klassischen Routendefinition führten MVC WEB API 2 und MVC 5-Frameworks das 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();
}
}
Für Routen mit demselben Präfix innerhalb eines Controllers können Sie mithilfe RoutePrefix
Attributs RoutePrefix
ein gemeinsames Präfix für gesamte Aktionsmethoden im Controller RoutePrefix
.
[RoutePrefix("Custom")]
public class CustomController : Controller
{
[Route("Index")]
public ActionResult Index()
{
...
}
}
RoutePrefix
ist optional und definiert den Teil der URL, der allen Aktionen des Controllers vorangestellt ist.
Wenn Sie über mehrere Routen verfügen, können Sie eine Standardroute festlegen, indem Sie action als Parameter erfassen und dann für den gesamten Controller anwenden, es sei denn, ein bestimmtes Route
ist für bestimmte Aktionsmethoden definiert, die die Standardroute überschreiben.
[RoutePrefix("Custom")]
[Route("{action=index}")]
public class CustomController : Controller
{
public ActionResult Index()
{
...
}
public ActionResult Detail()
{
...
}
}
Routing-Grundlagen
Wenn Sie die URL " yourSite/Home/Index
über einen Browser anfordern, yourSite/Home/Index
das Routing-Modul die Anforderung an die Index
Aktionsmethode der HomeController
Klasse weiter. Wie kann er die Anfrage an die spezifische Methode dieser Klasse senden? da kommt die RouteTable.
Jede Anwendung verfügt über eine Routentabelle, in der das Routenmuster und Informationen darüber gespeichert werden, wohin die Anforderung gerichtet werden soll. Wenn Sie also Ihre mvc-Anwendung erstellen, ist bereits eine Standardroute in der Routingtabelle registriert. Sie können das in der Klasse 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 });
}
Sie sehen, dass der Eintrag einen Namen und eine Vorlage hat. Die Vorlage ist das Routenmuster, das überprüft werden muss, wenn eine Anforderung eingeht. Die Standardvorlage enthält als Wert des Controller-URL-Segments Home
und als Wert für das Aktionssegment Index
. Das heißt, wenn Sie nicht explizit einen Controller-Namen und eine Aktion in Ihrer Anfrage übergeben, werden diese Standardwerte verwendet. Aus diesem Grund erhalten Sie dasselbe Ergebnis, wenn Sie auf yourSite/Home/Index
und yourSite
Sie haben vielleicht bemerkt, dass wir als letzten Abschnitt unseres Routenmusters einen Parameter namens id haben. In den Standardeinstellungen geben wir jedoch an, dass dies optional ist. Aus diesem Grund mussten wir nicht den ID-Wert in der URL angeben, die wir versucht haben.
Gehen Sie jetzt zurück zur Index-Aktionsmethode in HomeController und fügen Sie einen Parameter hinzu
public ActionResult Index(int id)
{
return View();
}
Fügen Sie nun einen visuellen Studio- Haltepunkt in diese Methode ein. Führen Sie Ihr Projekt aus und greifen yourSite/Home/Index/999
in Ihrem Browser auf Ihre yourSite/Home/Index/999
zu. Der Haltepunkt wird getroffen und Sie sollten sehen können, dass der Wert 999 jetzt im Parameter id
verfügbar ist.
Ein zweites Routenmuster erstellen
Nehmen wir an, wir möchten es so einrichten, dass dieselbe Aktionsmethode für ein anderes Routenmuster aufgerufen wird. Wir können dies tun, indem Sie der Routentabelle eine neue Routendefinition hinzufügen.
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 });
}
Die neue Definition, die ich hinzugefügt habe, hat ein Muster Important/{id}
wobei id erneut optional ist. Das bedeutet, wenn Sie yourSiteName\Important
oder yourSiteName\Important\888
, wird er an die Index-Aktion von HomeController gesendet.
Reihenfolge der Registrierung der Routendefinition
Die Reihenfolge der Routenregistrierung ist wichtig. Sie sollten die spezifischen Routenmuster immer vor einer Standardroute registrieren.
Catch-All-Route
Angenommen, wir möchten eine Route haben, die eine ungebundene Anzahl von Segmenten zulässt, wie folgt:
- http://example.com/Products/ (alle Produkte anzeigen)
- http://example.com/Products/IT
- http://example.com/Products/IT/Laptops
- http://example.com/Products/IT/Laptops/Ultrabook
- http://example.com/Products/IT/Laptops/Ultrabook/Asus
- usw.
Wir müssten eine Route hinzufügen, normalerweise am Ende der Routentabelle, da dies wahrscheinlich alle Anfragen fangen würde, z.
routes.MapRoute("Final", "Route/{*segments}",
new { controller = "Product", action = "View" });
In der Steuerung könnte eine Aktion, die damit umgehen könnte, sein:
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
// ...
}
Catch-All-Route zum Aktivieren des clientseitigen Routings
Es empfiehlt sich, den Status der Single Page Application (SPA) in der URL zu kodieren:
my-app.com/admin-spa/users/edit/id123
Dies ermöglicht das Speichern und Freigeben des Anwendungsstatus.
Wenn der Benutzer die URL in die Adressleiste des Browsers einfügt und die Eingabetaste trifft, muss der Server den clientseitigen Teil der angeforderten URL ignorieren. Wenn Sie Ihr SPA als gerenderte Razor-Ansicht (Ergebnis einer aufrufenden Controller-Aktion) anstelle einer statischen HTML-Datei bereitstellen, können Sie eine Catch-All-Route verwenden:
public class AdminSpaController
{
[Route("~/admin-spa/{clienSidePart*}")]
ActionResult AdminSpa()
{
...
}
}
In diesem Fall gibt der Server nur SPA zurück und initialisiert sich entsprechend der Route. Dieser Ansatz ist flexibler, da er nicht vom Url-Rewrite- Modul abhängt.
Attribut-Routing in Bereichen
Für die Verwendung von Attribut-Routing in Bereichen sind das Registrieren von Bereichen und die Definition von [RouteArea(...)]
erforderlich.
In RouteConfig.cs
:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
AreaRegistration.RegisterAllAreas();
}
}
In einer Beispiel-Routingdefinition für Bereichscontrollerattribute:
[RouteArea("AreaName", AreaPrefix = "AreaName")]
[RoutePrefix("SampleAreaController")]
public class SampleAreaController : Controller
{
[Route("Index")]
public ActionResult Index()
{
return View();
}
}
Um Url.Action
Links in Bereichen zu verwenden:
@Url.Action("Index", "SampleAreaController", new { area = "AreaName" })