Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Von Steve Smith
ASP.NET Core MVC definiert ein Anwendungsmodell , das die Komponenten einer MVC-App darstellt. Lesen und bearbeiten Sie dieses Modell, um das Verhalten von MVC-Elementen zu ändern. MVC folgt standardmäßig bestimmten Konventionen, um zu bestimmen, welche Klassen als Controller gelten, welche Methoden für diese Klassen Aktionen sind und wie Sich Parameter und Routing verhalten. Passen Sie dieses Verhalten an die Anforderungen einer App an, indem Sie benutzerdefinierte Konventionen erstellen und global oder als Attribute anwenden.
Modelle und Anbieter (IApplicationModelProvider)
Das ASP.NET Core MVC-Anwendungsmodell enthält sowohl abstrakte Schnittstellen als auch konkrete Implementierungsklassen, die eine MVC-Anwendung beschreiben. Dieses Modell ist das Ergebnis, dass MVC die Controller, Aktionen, Aktionsparameter, Routen und Filter entsprechend den Standardkonventionen ermittelt. Indem Sie mit dem Anwendungsmodell arbeiten, ändern Sie eine App so, dass sie unterschiedliche Konventionen vom standardmäßigen MVC-Verhalten befolgt. Die Parameter, Namen, Routen und Filter werden alle als Konfigurationsdaten für Aktionen und Controller verwendet.
Das ASP.NET Core MVC-Anwendungsmodell weist die folgende Struktur auf:
- ApplicationModel
- Controller (ControllerModel)
- Actions (ActionModel)
- Parameter (ParameterModel)
- Actions (ActionModel)
- Controller (ControllerModel)
Jede Ebene des Modells hat Zugriff auf eine allgemeine Properties Auflistung, und niedrigere Ebenen können auf Eigenschaftswerte zugreifen und überschreiben, die durch höhere Ebenen in der Hierarchie festgelegt werden. Die Eigenschaften werden im ActionDescriptor.Properties gespeichert, wenn die Aktionen erstellt werden. Wenn eine Anforderung verarbeitet wird, dann kann auf alle Eigenschaften, die eine Konvention hinzugefügt oder geändert hat, über ActionContext.ActionDescriptor zugegriffen werden. Die Verwendung von Eigenschaften ist eine hervorragende Möglichkeit zum Konfigurieren von Filtern, Modellordnern und anderen App-Modellaspekten pro Aktion.
Hinweis
Die ActionDescriptor.Properties Sammlung ist nach dem Starten der App nicht threadsicher (für Schreibvorgänge). Konventionen sind die beste Möglichkeit, daten sicher zu dieser Sammlung hinzuzufügen.
ASP.NET Core MVC lädt das Anwendungsmodell mithilfe eines Anbietermusters, das von der IApplicationModelProvider Schnittstelle definiert wird. In diesem Abschnitt werden einige der internen Implementierungsdetails erläutert, wie dieser Anbieter funktioniert. Die Verwendung des Provider-Musters ist ein fortgeschrittenes Thema, das in erster Linie für die Verwendung innerhalb von Frameworks gedacht ist. Die meisten Apps sollten Konventionen verwenden, nicht das Anbietermuster.
Implementierungen der IApplicationModelProvider-Schnittstelle "umschließen" einander, wobei jede Implementierung basierend auf ihrer Order-Eigenschaft in aufsteigender Reihenfolge OnProvidersExecuting aufruft. Die OnProvidersExecuted Methode wird dann in umgekehrter Reihenfolge aufgerufen. Das Framework definiert mehrere Anbieter:
Zuerst (Order=-1000):
DefaultApplicationModelProvider
Dann (Order=-990):
AuthorizationApplicationModelProviderCorsApplicationModelProvider
Hinweis
Die Reihenfolge, in der zwei Anbieter mit demselben Wert für Order aufgerufen werden, ist nicht definiert und es sollte nicht darauf vertraut werden.
Hinweis
IApplicationModelProvider ist ein fortschrittliches Konzept, das von Framework-Autoren erweitert werden kann. Im Allgemeinen sollten Apps Konventionen verwenden, und Frameworks sollten Anbieter verwenden. Der wichtigste Unterschied besteht darin, dass Anbieter immer vor Konventionen ausgeführt werden.
Dies DefaultApplicationModelProvider stellt viele der Standardverhaltensweisen fest, die von ASP.NET Core MVC verwendet werden. Zu den Verantwortlichkeiten gehören:
- Hinzufügen globaler Filter zum Kontext
- Hinzufügen von Controllern zum Kontext
- Hinzufügen von öffentlichen Controller-Methoden als Aktionen
- Hinzufügen von Aktionsmethodenparametern zum Kontext
- Anwenden von Routen und anderen Attributen
Einige integrierte Verhaltensweisen werden von DefaultApplicationModelProvider implementiert. Dieser Anbieter ist für die Erstellung der ControllerModel verantwortlich, die wiederum auf ActionModel, PropertyModel und ParameterModel Instanzen verweist. Die DefaultApplicationModelProvider Klasse ist ein internes Frameworkimplementierungsdetails, das sich in Zukunft ändern kann.
Das AuthorizationApplicationModelProvider ist für das Anwenden des Verhaltens verantwortlich, das mit den Attributen AuthorizeFilter und AllowAnonymousFilter verknüpft ist. Weitere Informationen finden Sie unter "Einfache Autorisierung" in ASP.NET Core.
Das CorsApplicationModelProvider implementiert Verhalten, das mit IEnableCorsAttribute und IDisableCorsAttribute verbunden ist. Weitere Informationen finden Sie unter Aktivierung von Cross-Origin Requests (CORS) in ASP.NET Core.
Informationen zu den in diesem Abschnitt beschriebenen internen Anbietern des Frameworks sind nicht über den .NET-API-Browser verfügbar. Die Anbieter können jedoch im ASP.NET Core-Referenzquelle (dotnet/aspnetcore GitHub-Repository) geprüft werden. Verwenden Sie die GitHub-Suche, um die Anbieter anhand des Namens zu finden und die Version der Quelle mit der Dropdownliste "Switch branches/tags " auszuwählen.
Conventions
Das Anwendungsmodell definiert Konventionsabstraktionen, die eine einfachere Möglichkeit zum Anpassen des Verhaltens der Modelle bieten, als das gesamte Modell oder den gesamten Anbieter außer Kraft zu setzen. Diese Abstraktionen sind die empfohlene Methode, um das Verhalten einer App zu ändern. Konventionen bieten eine Möglichkeit zum Schreiben von Code, der Anpassungen dynamisch anwendet. Während Filter eine Möglichkeit bieten, das Verhalten des Frameworks zu ändern, ermöglichen Anpassungen die Kontrolle darüber, wie die gesamte App zusammenarbeitet.
Die folgenden Konventionen sind verfügbar:
- IApplicationModelConvention
- IControllerModelConvention
- IActionModelConvention
- IParameterModelConvention
Konventionen werden angewendet, indem sie zu MVC-Optionen hinzugefügt werden, oder indem Attribute implementiert und auf Controller, Aktionen oder Aktionsparameter angewendet werden (ähnlich wie Filter). Im Gegensatz zu Filtern werden Konventionen nur ausgeführt, wenn die App gestartet wird, nicht als Teil jeder Anforderung.
Hinweis
Informationen zu Seitenrouten- und Anwendungsmodellanbieterkonventionen finden Sie unter Razor.
Ändern Sie ApplicationModel
Die folgende Konvention wird verwendet, um dem Anwendungsmodell eine Eigenschaft hinzuzufügen:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class ApplicationDescription : IApplicationModelConvention
{
private readonly string _description;
public ApplicationDescription(string description)
{
_description = description;
}
public void Apply(ApplicationModel application)
{
application.Properties["description"] = _description;
}
}
}
Anwendungsmodellkonventionen werden als Optionen angewendet, wenn MVC hinzugefügt wird:Startup.ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
Auf Eigenschaften kann über die Auflistung innerhalb von ActionDescriptor.Properties Controlleraktionen zugegriffen werden:
public class AppModelController : Controller
{
public string Description()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
}
Ändern der ControllerModel Beschreibung
Das Controllermodell kann auch benutzerdefinierte Eigenschaften enthalten. Benutzerdefinierte Eigenschaften überschreiben vorhandene Eigenschaften mit demselben Namen, der im Anwendungsmodell angegeben ist. Das folgende Konventionsattribut fügt eine Beschreibung auf Controllerebene hinzu:
using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class ControllerDescriptionAttribute : Attribute, IControllerModelConvention
{
private readonly string _description;
public ControllerDescriptionAttribute(string description)
{
_description = description;
}
public void Apply(ControllerModel controllerModel)
{
controllerModel.Properties["description"] = _description;
}
}
}
Diese Konvention wird als Attribut auf einem Controller angewendet:
[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
public string Index()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
Ändern der ActionModel Beschreibung
Eine separate Attributkonvention kann auf einzelne Aktionen angewendet werden, um das Verhalten zu überschreiben, das bereits auf Anwendungs- oder Controllerebene angewendet wurde.
using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class ActionDescriptionAttribute : Attribute, IActionModelConvention
{
private readonly string _description;
public ActionDescriptionAttribute(string description)
{
_description = description;
}
public void Apply(ActionModel actionModel)
{
actionModel.Properties["description"] = _description;
}
}
}
Das Anwenden auf eine Aktion innerhalb des Controllers veranschaulicht, wie die Konvention auf Controllerebene außer Kraft gesetzt wird:
[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
public string Index()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
[ActionDescription("Action Description")]
public string UseActionDescriptionAttribute()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
}
Ändern Sie das ParameterModel
Die folgende Konvention kann auf Aktionsparameter angewendet werden, um deren BindingInfoParameter zu ändern. Für die folgende Konvention muss der Parameter ein Routenparameter sein. Andere potenzielle Bindungsquellen, z. B. Abfragezeichenfolgenwerte, werden ignoriert:
using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace AppModelSample.Conventions
{
public class MustBeInRouteParameterModelConvention : Attribute, IParameterModelConvention
{
public void Apply(ParameterModel model)
{
if (model.BindingInfo == null)
{
model.BindingInfo = new BindingInfo();
}
model.BindingInfo.BindingSource = BindingSource.Path;
}
}
}
Das Attribut kann auf jeden Aktionsparameter angewendet werden:
public class ParameterModelController : Controller
{
// Will bind: /ParameterModel/GetById/123
// WON'T bind: /ParameterModel/GetById?id=123
public string GetById([MustBeInRouteParameterModelConvention]int id)
{
return $"Bound to id: {id}";
}
}
Um die Konvention auf alle Aktionsparameter anzuwenden, fügen Sie MustBeInRouteParameterModelConvention zu MvcOptions in Startup.ConfigureServices hinzu.
options.Conventions.Add(new MustBeInRouteParameterModelConvention());
Ändern des ActionModel Namens
Die folgende Konvention modifiziert den ActionModel und aktualisiert den Name der Aktion, auf die sie angewendet wird. Der neue Name wird als Parameter für das Attribut bereitgestellt. Dieser neue Name wird vom Routing verwendet, sodass er sich auf die Route auswirkt, die verwendet wird, um diese Aktionsmethode zu erreichen:
using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class CustomActionNameAttribute : Attribute, IActionModelConvention
{
private readonly string _actionName;
public CustomActionNameAttribute(string actionName)
{
_actionName = actionName;
}
public void Apply(ActionModel actionModel)
{
// this name will be used by routing
actionModel.ActionName = _actionName;
}
}
}
Dieses Attribut wird auf eine Aktionsmethode im HomeController angewendet.
// Route: /Home/MyCoolAction
[CustomActionName("MyCoolAction")]
public string SomeName()
{
return ControllerContext.ActionDescriptor.ActionName;
}
Obwohl der Methodenname lautet SomeName, überschreibt das Attribut die MVC-Konvention der Verwendung des Methodennamens und ersetzt den Aktionsnamen durch MyCoolAction. Daher ist /Home/MyCoolActiondie Route, die verwendet wird, um diese Aktion zu erreichen.
Hinweis
Dieses Beispiel in diesem Abschnitt entspricht im Wesentlichen der Verwendung der integrierten ActionNameAttribute.
Benutzerdefinierte Routingkonvention
Verwenden Sie ein IApplicationModelConvention, um die Funktionsweise des Routings anzupassen. Die folgende Konvention enthält beispielsweise die Namespaces von Controllern in ihren Routen, wobei . im Namespace durch / in der Route ersetzt wird.
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;
namespace AppModelSample.Conventions
{
public class NamespaceRoutingConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
var hasAttributeRouteModels = controller.Selectors
.Any(selector => selector.AttributeRouteModel != null);
if (!hasAttributeRouteModels
&& controller.ControllerName.Contains("Namespace")) // affect one controller in this sample
{
// Replace the . in the namespace with a / to create the attribute route
// Ex: MySite.Admin namespace will correspond to MySite/Admin attribute route
// Then attach [controller], [action] and optional {id?} token.
// [Controller] and [action] is replaced with the controller and action
// name to generate the final template
controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel()
{
Template = controller.ControllerType.Namespace.Replace('.', '/') + "/[controller]/[action]/{id?}"
};
}
}
// You can continue to put attribute route templates for the controller actions depending on the way you want them to behave
}
}
}
Die Konvention wird als Option hinzugefügt in Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
Tipp
Fügen Sie Konventionen zu Middleware mithilfe von MvcOptions unter Verwendung des folgenden Ansatzes hinzu. Der {CONVENTION} Platzhalter ist die Konvention zum Hinzufügen:
services.Configure<MvcOptions>(c => c.Conventions.Add({CONVENTION}));
Im folgenden Beispiel wird eine Konvention auf Routen angewendet, die kein Attributrouting verwenden, bei denen der Controller Namespace im Namen hat:
using Microsoft.AspNetCore.Mvc;
namespace AppModelSample.Controllers
{
public class NamespaceRoutingController : Controller
{
// using NamespaceRoutingConvention
// route: /AppModelSample/Controllers/NamespaceRouting/Index
public string Index()
{
return "This demonstrates namespace routing.";
}
}
}
Anwendungsmodellverwendung in WebApiCompatShim
ASP.NET Core MVC verwendet einen anderen Satz von Konventionen von ASP.NET Web-API 2. Mit benutzerdefinierten Konventionen können Sie das Verhalten einer ASP.NET Core MVC-App so ändern, dass sie mit der einer Web-API-App konsistent ist. Microsoft liefert das WebApiCompatShim NuGet-Paket speziell für diesen Zweck.
Hinweis
Weitere Informationen zur Migration von ASP.NET Web-API finden Sie unter Migrieren von ASP.NET Web-API zu ASP.NET Core.
So verwenden Sie den Web-API-Kompatibilitäts-Shim:
- Fügen Sie das
Microsoft.AspNetCore.Mvc.WebApiCompatShimPaket dem Projekt hinzu. - Fügen Sie die Konventionen zu MVC hinzu, indem Sie AddWebApiConventions in
Startup.ConfigureServicesaufrufen.
services.AddMvc().AddWebApiConventions();
Die vom Shim bereitgestellten Konventionen werden nur auf Teile der App angewendet, denen bestimmte Attribute zugeordnet wurden. Die folgenden vier Attribute werden verwendet, um zu steuern, bei welchen Controllern die Konventionen durch die Shim-Konventionen geändert werden sollen:
- UseWebApiActionConventionsAttribute
- UseWebApiOverloadingAttribute
- UseWebApiParameterConventionsAttribute
- UseWebApiRoutesAttribute
Aktionskonventionen
UseWebApiActionConventionsAttribute wird verwendet, um die HTTP-Methode auf Aktionen basierend auf ihrem Namen abzubilden (zum Beispiel würde Get zu HttpGet zugeordnet werden). Sie gilt nur für Aktionen, die kein Attributrouting verwenden.
Überladen
UseWebApiOverloadingAttribute wird verwendet, um die WebApiOverloadingApplicationModelConvention Konvention anzuwenden. Diese Konvention fügt dem Aktionsauswahlprozess einen OverloadActionConstraint Wert hinzu, der Kandidatenaktionen auf diejenigen beschränkt, für die die Anforderung alle nicht optionalen Parameter erfüllt.
Parameterkonventionen
UseWebApiParameterConventionsAttribute wird verwendet, um die WebApiParameterConventionsApplicationModelConvention Aktionskonvention anzuwenden. Diese Konvention gibt an, dass einfache Typen, die als Aktionsparameter verwendet werden, standardmäßig vom URI gebunden sind, während komplexe Typen vom Anforderungstext gebunden sind.
Routen
UseWebApiRoutesAttribute steuert, ob die WebApiApplicationModelConvention Controllerkonvention angewendet wird. Wenn diese Konvention aktiviert ist, wird diese Konvention verwendet, um Unterstützung für Bereiche zur Route hinzuzufügen und angibt, dass sich der api Controller im Bereich befindet.
Zusätzlich zu einer Reihe von Konventionen enthält das Kompatibilitätspaket eine System.Web.Http.ApiController Basisklasse, die die von der Web-API bereitgestellte ersetzt. Dies ermöglicht Ihren Web-API-Controllern, die für die Web-API geschrieben wurden und die von ApiController erben, während der Ausführung auf ASP.NET Core MVC zu funktionieren.
UseWebApi* Alle zuvor aufgeführten Attribute werden auf die Basiscontrollerklasse angewendet. Dies ApiController macht Eigenschaften, Methoden und Ergebnistypen verfügbar, die mit den in der Web-API gefundenen typen kompatibel sind.
Verwenden Sie ApiExplorer, um eine App zu dokumentieren
Das Anwendungsmodell macht eine ApiExplorerModel Eigenschaft auf jeder Ebene verfügbar, die zum Durchlaufen der App-Struktur verwendet werden kann. Dies kann verwendet werden, um Hilfeseiten für Web-APIs mithilfe von Tools wie Swagger zu generieren. Die ApiExplorer Eigenschaft macht eine IsVisible Eigenschaft verfügbar, die festgelegt werden kann, um anzugeben, welche Teile des App-Modells verfügbar gemacht werden sollen. Konfigurieren Sie diese Einstellung mithilfe einer Konvention:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class EnableApiExplorerApplicationConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
application.ApiExplorer.IsVisible = true;
}
}
}
Bei Verwendung dieses Ansatzes (und ggf. zusätzlicher Konventionen) wird die API-Sichtbarkeit auf jeder Ebene innerhalb einer App aktiviert oder deaktiviert.