Práce s aplikačním modelem v ASP.NET Core
Od Steve Smith
ASP.NET Core MVC definuje aplikační model představující komponenty aplikace MVC. Čtením a manipulací s tímto modelem můžete upravit chování elementů MVC. Ve výchozím nastavení se MVC řídí určitými konvencemi a určuje, které třídy jsou považovány za kontrolery, které metody v těchto třídách jsou akce a jak se parametry a směrování chovají. Toto chování můžete přizpůsobit tak, aby vyhovovalo potřebám aplikace, a to tak, že vytvoříte vlastní konvence a použijete je globálně nebo jako atributy.
Modely a poskytovatelé ( IApplicationModelProvider )
Model ASP.NET Core MVC zahrnuje abstraktní rozhraní i konkrétní třídy implementace, které popisují aplikaci MVC. Tento model je výsledkem MVC, který zjišťuje kontrolery, akce, parametry akce, trasy a filtry aplikace podle výchozích konvencí. Když pracujete s aplikačním modelem, upravte aplikaci tak, aby se lichaly různými konvencemi od výchozího chování MVC. Parametry, názvy, trasy a filtry se používají jako konfigurační data pro akce a kontrolery.
Model ASP.NET Core MVC má následující strukturu:
- Model Aplikace
- Kontrolery (ControllerModel)
- Akce (ActionModel)
- Parametry (ParameterModel)
- Akce (ActionModel)
- Kontrolery (ControllerModel)
Každá úroveň modelu má přístup ke společné kolekci a nižší úrovně mají přístup k hodnotám vlastností nastaveným vyššími úrovněmi v hierarchii a Properties přepisovat je. Vlastnosti se při vytváření akcí uchová ActionDescriptor.Properties v objektu . Při zpracování požadavku jsou pak prostřednictvím přístupné všechny vlastnosti přidané nebo upravené ActionContext.ActionDescriptor konvence. Použití vlastností je skvělý způsob, jak konfigurovat filtry, važe modelu a další aspekty modelu aplikací pro každou akci.
Poznámka
Kolekce není bezpečná pro přístup z více vláken ActionDescriptor.Properties (pro zápisy) po spuštění aplikace. Nejlepším způsobem, jak do této kolekce bezpečně přidávat data, jsou konvence.
ASP.NET Core MVC načte aplikační model pomocí vzoru zprostředkovatele definovaného IApplicationModelProvider rozhraním. Tato část se věnuje některým podrobnostem o interní implementaci, jak tento zprostředkovatel funguje. Použití vzoru poskytovatele je rozšířené téma, především pro použití architektury. Většina aplikací by měla používat konvence, nikoli model poskytovatele.
Implementace rozhraní se "zalamují", kdy každá implementace volá ve vzestupném pořadí IApplicationModelProvider OnProvidersExecuting na základě své Order vlastnosti. Metoda OnProvidersExecuted se pak volá v opačném pořadí. Rozhraní definuje několik poskytovatelů:
První ( Order=-1000 ):
DefaultApplicationModelProvider
Potom ( Order=-990 ):
AuthorizationApplicationModelProviderCorsApplicationModelProvider
Poznámka
Pořadí, ve kterém jsou volány dva zprostředkovatelé se stejnou hodnotou pro , není definováno a nemělo by se Order na něj spoléhat.
Poznámka
IApplicationModelProvider je pokročilý koncept, který rozšiřují autoři architektury. Obecně platí, že aplikace by měly používat konvence a architektury by měly používat zprostředkovatele. Hlavní rozdíl je v tom, že poskytovatelé vždy běží před konvencemi.
Vytváří DefaultApplicationModelProvider mnoho výchozích chování používaných ASP.NET Core MVC. Mezi jeho zodpovědnosti patří:
- Přidání globálních filtrů do kontextu
- Přidání kontrolerů do kontextu
- Přidání metod veřejného kontroleru jako akcí
- Přidání parametrů metody akce do kontextu
- Použití trasy a dalších atributů
Některé předdefinované chování jsou implementovány pomocí DefaultApplicationModelProvider . Tento zprostředkovatel zodpovídá za vytvoření , který zase odkazuje na ControllerModel ActionModel instance , a PropertyModel ParameterModel . Třída DefaultApplicationModelProvider je podrobnostmi implementace interní architektury, které se mohou v budoucnu změnit.
AuthorizationApplicationModelProviderzodpovídá za použití chování přidruženého k AuthorizeFilter atributům AllowAnonymousFilter a . Další informace naleznete v tématu Jednoduchá autorizace v ASP.NET Core.
Implementuje CorsApplicationModelProvider chování přidružené k a IEnableCorsAttribute IDisableCorsAttribute . Další informace naleznete v tématu Povolit žádosti mezi zdroji (CORS) v ASP.NET Core.
Informace o interních poskytovatelích rozhraní popsané v této části nejsou dostupné prostřednictvím prohlížeče rozhraní .NET API. Poskytovatelé však mohou být prověřen v referenčním ASP.NET Core (dotnet/aspnetcoreGitHub úložiště) . Pomocí GitHub vyhledejte zprostředkovatele podle názvu a vyberte verzi zdroje pomocí rozevíracího seznamu Switch branches/tags (Přepnout větve/značky).
Konvence
Aplikační model definuje abstrakce konvence, které poskytují jednodušší způsob přizpůsobení chování modelů než přepsání celého modelu nebo zprostředkovatele. Tyto abstrakce jsou doporučeným způsobem, jak upravit chování aplikace. Konvence poskytují způsob, jak napsat kód, který dynamicky aplikuje přizpůsobení. Filtry sice umožňují změnit chování architektury, ale přizpůsobení umožňují řídit, jak celá aplikace funguje společně.
K dispozici jsou následující konvence:
- IApplicationModelConvention
- IControllerModelConvention
- IActionModelConvention
- IParameterModelConvention
Konvence se používají tak, že je přidáte do možností MVC nebo implementací atributů a použijete je na kontrolery, akce nebo parametry akce (podobně jako filtry). Na rozdíl od filtrů se konvence provádějí pouze při spuštění aplikace, nikoli jako součást každého požadavku.
Poznámka
Informace o směrování Razor Pages a konvencích poskytovatelů aplikačních modelů najdete v tématu RazorSměrování stránek a konvence aplikací v ASP.NET Core .
Upravte ApplicationModel
Následující konvence slouží k přidání vlastnosti do aplikačního modelu:
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;
}
}
}
Při přidání MVC do se jako možnosti použijí konvence aplikačního Startup.ConfigureServices modelu:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
Vlastnosti jsou přístupné z ActionDescriptor.Properties kolekce v rámci akcí kontroleru:
public class AppModelController : Controller
{
public string Description()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
}
Úprava ControllerModel popisu
Model kontroleru může obsahovat také vlastní vlastnosti. Vlastní vlastnosti přepíší existující vlastnosti se stejným názvem, který je zadaný v aplikačním modelu. Následující atribut konvence přidá popis na úrovni kontroleru:
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;
}
}
}
Tato konvence se použije jako atribut v kontroleru:
[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
public string Index()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
Úprava ActionModel popisu
Na jednotlivé akce je možné použít samostatnou konvenci atributů, která přepíše chování, které se už použilo na úrovni aplikace nebo kontroleru:
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;
}
}
}
Použití této vlastnosti u akce v rámci kontroleru ukazuje, jak přepisuje konvenci na úrovni kontroleru:
[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"];
}
}
Upravte ParameterModel
Následující konvence se může použít u parametrů akce, aby se upravují BindingInfo jejich hodnoty . Následující konvence vyžaduje, aby parametr byl parametr trasy. Ostatní potenciální zdroje vazeb, například hodnoty řetězce dotazu, se ignorují:
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;
}
}
}
Atribut lze použít na libovolný parametr akce:
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}";
}
}
Pokud chcete konvenci použít na všechny parametry akce, přidejte MustBeInRouteParameterModelConvention do MvcOptions do Startup.ConfigureServices :
options.Conventions.Add(new MustBeInRouteParameterModelConvention());
Úprava ActionModel názvu
Následující konvence upraví a ActionModel aktualizuje název akce, na kterou se použije. Nový název je zadán jako parametr atributu. Tento nový název se používá směrováním, takže má vliv na trasu použitou k dosažení této metody akce:
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;
}
}
}
Tento atribut se použije na metodu akce v HomeController :
// Route: /Home/MyCoolAction
[CustomActionName("MyCoolAction")]
public string SomeName()
{
return ControllerContext.ActionDescriptor.ActionName;
}
I když je název metody , přepíše atribut konvenci MVC použití názvu metody a nahradí SomeName název akce názvem MyCoolAction . Trasa použitá k dosažení této akce je /Home/MyCoolAction tedy .
Poznámka
Tento příklad v této části je v podstatě stejný jako použití ActionNameAttribute integrovaného .
Vlastní konvence směrování
K přizpůsobení IApplicationModelConvention toho, jak směrování funguje, použijte . Například následující konvence začleňuje obory názvů kontrolerů do jejich tras a nahradí v oboru názvů . v / trase za :
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
}
}
}
Konvence se přidá jako možnost v Startup.ConfigureServices :
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
Tip
Pomocí následujícího přístupu přidejte do middlewaru MvcOptions konvence. Zástupný {CONVENTION} symbol je konvence pro přidání:
services.Configure<MvcOptions>(c => c.Conventions.Add({CONVENTION}));
Následující příklad používá konvenci pro trasy, které nepou3/4í směrování atributů, kde má kontroler Namespace svůj název:
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.";
}
}
}
Využití aplikačního modelu v WebApiCompatShim
ASP.NET Core MVC používá jinou sadu konvencí než ASP.NET API 2. Pomocí vlastních konvencí můžete upravit chování ASP.NET Core MVC tak, aby bylo konzistentní s chováním webové aplikace API. Microsoft dodává balíček WebApiCompatShim NuGet speciálně pro tento účel.
Poznámka
Další informace o migraci z webového ASP.NET API najdete v tématu Migrace z ASP.NET Web API na ASP.NET Core .
Použití překrytí kompatibility webového rozhraní API:
- Přidejte
Microsoft.AspNetCore.Mvc.WebApiCompatShimbalíček do projektu. - Přidejte do MVC konvence voláním AddWebApiConventions v
Startup.ConfigureServices:
services.AddMvc().AddWebApiConventions();
Konvence překrytí se aplikují jenom na části aplikace, u kterých se používají určité atributy. Následující čtyři atributy slouží k řízení, které řadiče by měly mít své konvence upravené konvencemi překrytí:
- UseWebApiActionConventionsAttribute
- UseWebApiOverloadingAttribute
- UseWebApiParameterConventionsAttribute
- UseWebApiRoutesAttribute
Konvence akcí
UseWebApiActionConventionsAttribute slouží k mapování metody HTTP na akce založené na jejich názvu (například Get by namapovaly na HttpGet ). Vztahuje se pouze na akce, které nepoužívají směrování atributů.
Přetížení
UseWebApiOverloadingAttribute slouží k použití WebApiOverloadingApplicationModelConvention úmluvy. Tato konvence přičítá OverloadActionConstraint k procesu výběru akce, který omezuje akce kandidáta na ty, pro které požadavek splňuje všechny nepovinné parametry.
Konvence parametrů
UseWebApiParameterConventionsAttribute slouží k použití WebApiParameterConventionsApplicationModelConvention úmluvy akce. Tato konvence určuje, že jednoduché typy používané jako parametry akce jsou ve výchozím nastavení vázány z identifikátoru URI, zatímco komplexní typy jsou vázány z textu žádosti.
Trasy
UseWebApiRoutesAttribute Určuje, zda WebApiApplicationModelConvention je použita konvence kontroleru. Pokud je tato konvence povolená, použije se k přidání podpory pro oblasti do trasy a označuje, že se kontroler nachází v api oblasti.
Kromě sady konvencí balíček kompatibility zahrnuje System.Web.Http.ApiController základní třídu, která nahrazuje rozhraní API, které poskytuje webové rozhraní API. to umožňuje, aby vaše řadiče webového rozhraní api byly napsané pro webové rozhraní api a dědily z jejího ApiController fungování na ASP.NET Core MVC. Všechny výše UseWebApi* uvedené atributy jsou aplikovány na základní třídu kontroleru. ApiControllerZpřístupňuje vlastnosti, metody a typy výsledků, které jsou kompatibilní s metodami nalezenými ve webovém rozhraní API.
Použití ApiExplorer k dokumentaci aplikace
Aplikační model zpřístupňuje ApiExplorerModel vlastnost na každé úrovni, kterou lze použít k procházení struktury aplikace. Dá se použít ke generování stránek s nápovědu pro webová rozhraní API pomocí nástrojů jako Swagger. ApiExplorerVlastnost zpřístupňuje IsVisible vlastnost, která může být nastavena tak, aby určovala, které části modelu aplikace by měly být vystaveny. Nakonfigurujte toto nastavení pomocí konvence:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class EnableApiExplorerApplicationConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
application.ApiExplorer.IsVisible = true;
}
}
}
Pomocí tohoto přístupu (a dalších konvencí v případě potřeby) je viditelnost rozhraní API povolená nebo zakázaná na libovolné úrovni aplikace.