작성자 Steve Smith
ASP.NET Core MVC는 MVC 앱의 구성 요소를 나타내는 애플리케이션 모델을 정의합니다. 이 모델을 읽고 조작하여 MVC 요소의 동작 방식을 수정합니다. 기본적으로 MVC는 특정 규칙을 따라 컨트롤러로 간주되는 클래스, 해당 클래스의 메서드가 작업인 방법 및 매개 변수 및 라우팅이 작동하는 방식을 결정합니다. 사용자 지정 규칙을 만들고 전역적으로 또는 특성으로 적용하여 앱의 요구에 맞게 이 동작을 사용자 지정합니다.
모델 및 공급자(IApplicationModelProvider)
ASP.NET Core MVC 애플리케이션 모델에는 추상 인터페이스와 MVC 애플리케이션을 설명하는 구체적인 구현 클래스가 모두 포함되어 있습니다. 이 모델은 MVC가 기본 규칙에 따라 앱의 컨트롤러, 작업, 작업 매개 변수, 경로 및 필터를 검색한 결과입니다. 애플리케이션 모델을 사용하여 기본 MVC 동작과 다른 규칙을 따르도록 앱을 수정합니다. 매개 변수, 이름, 경로 및 필터는 모두 작업 및 컨트롤러에 대한 구성 데이터로 사용됩니다.
ASP.NET Core MVC 애플리케이션 모델에는 다음과 같은 구조가 있습니다.
- ApplicationModel
- 컨트롤러(ControllerModel)
- 작업(액션 모델)
- 매개변수(ParameterModel)
- 작업(액션 모델)
- 컨트롤러(ControllerModel)
모델의 각 수준은 공통 Properties 컬렉션에 액세스할 수 있으며, 하위 수준은 계층 구조에서 상위 수준으로 설정된 속성 값에 액세스하고 덮어쓸 수 있습니다. 속성은 작업이 생성될 때 ActionDescriptor.Properties에 저장됩니다. 그런 다음 요청이 처리될 때, 관례가 추가하거나 수정한 모든 속성에 ActionContext.ActionDescriptor을 통해 액세스할 수 있습니다. 속성을 사용하면 작업별로 필터, 모델 바인더 및 기타 앱 모델 측면을 구성할 수 있습니다.
비고
앱 시작 후 컬렉션은 ActionDescriptor.Properties 스레드로부터 안전하지 않습니다(쓰기용). 규칙은 이 컬렉션에 데이터를 안전하게 추가하는 가장 좋은 방법입니다.
ASP.NET Core MVC는 인터페이스에서 정의한 공급자 패턴을 사용하여 애플리케이션 모델을 로드합니다 IApplicationModelProvider . 이 섹션에서는 이 공급자가 작동하는 방법에 대한 몇 가지 내부 구현 세부 정보를 설명합니다. 공급자 패턴의 사용은 주로 프레임워크 사용을 위한 고급 주제입니다. 대부분의 앱은 공급자 패턴이 아닌 규칙을 사용해야 합니다.
인터페이스의 IApplicationModelProvider 구현은 서로를 감쌉니다. 여기서 각 구현은 그 OnProvidersExecuting 속성에 따라 오름차순으로 Order를 호출합니다. OnProvidersExecuted 그런 다음 메서드를 역순으로 호출합니다. 프레임워크는 다음과 같은 여러 공급자를 정의합니다.
첫 번째(Order=-1000):
DefaultApplicationModelProvider
그런 다음(Order=-990):
AuthorizationApplicationModelProviderCorsApplicationModelProvider
비고
동일한 값을 Order 가진 두 공급자가 호출되는 순서는 정의되지 않으며 의존해서는 안 됩니다.
비고
IApplicationModelProvider 는 프레임워크 작성자가 확장할 수 있는 고급 개념입니다. 일반적으로 앱은 규칙을 사용해야 하며 프레임워크는 공급자를 사용해야 합니다. 주요 차이점은 공급자가 항상 규약 전에 실행된다는 것입니다.
이 설정은 DefaultApplicationModelProvider ASP.NET Core MVC에서 사용하는 많은 기본 동작을 설정합니다. 책임은 다음과 같습니다.
- 컨텍스트에 전역 필터 추가
- 컨텍스트에 컨트롤러 추가
- 공용 컨트롤러 메서드를 작업으로 추가
- 컨텍스트에 작업 메서드 매개 변수 추가
- 경로 및 기타 특성 적용
일부 내장된 동작은 DefaultApplicationModelProvider에 의해 구현됩니다. 이 공급자는 ControllerModel를 구성하며, 이는 차례로 ActionModel, PropertyModel, 및 ParameterModel 인스턴스를 참조합니다. 클래스는 DefaultApplicationModelProvider 나중에 변경될 수 있는 내부 프레임워크 구현 세부 정보입니다.
AuthorizationApplicationModelProvider는 AuthorizeFilter 및 AllowAnonymousFilter 특성과 관련된 동작을 적용할 책임이 있습니다. 자세한 내용은 ASP.NET Core의 단순 권한 부여를 참조하세요.
CorsApplicationModelProvider는 IEnableCorsAttribute 및 IDisableCorsAttribute와 관련된 동작을 구현합니다. 자세한 내용은 ASP.NET Core에서 원본 간 요청(CORS) 사용 설정 를 참조하세요.
이 섹션에 설명된 프레임워크의 내부 공급자에 대한 정보는 .NET API 브라우저를 통해 사용할 수 없습니다. 그러나 공급자는 ASP.NET Core 참조 원본(dotnet/aspnetcore GitHub 리포지토리)에서 검사할 수 있습니다. GitHub 검색을 사용하여 이름으로 공급자를 찾고 분기/태그 전환 드롭다운 목록을 사용하여 원본 버전을 선택합니다.
관습
애플리케이션 모델은 전체 모델 또는 공급자를 재정의하는 것보다 모델의 동작을 사용자 지정하는 더 간단한 방법을 제공하는 규칙 추상화에 대해 정의합니다. 이러한 추상화는 앱의 동작을 수정하는 데 권장되는 방법입니다. 규칙은 사용자 지정을 동적으로 적용하는 코드를 작성하는 방법을 제공합니다. 필터는 프레임워크의 동작을 수정하는 방법을 제공하지만 사용자 지정은 전체 앱이 함께 작동하는 방식을 제어할 수 있도록 합니다.
다음 규칙을 사용할 수 있습니다.
- IApplicationModelConvention
- IControllerModelConvention
- IActionModelConvention
- IParameterModelConvention
규칙은 MVC 옵션에 추가하거나 특성을 구현하고 컨트롤러, 작업 또는 작업 매개 변수(필터와 유사)에 적용하여 적용 됩니다. 필터와 달리 규칙은 각 요청의 일부가 아니라 앱이 시작될 때만 실행됩니다.
비고
Pages 경로 및 애플리케이션 모델 공급자 규칙에 대한 Razor 자세한 내용은 ASP.NET Core의 Pages 경로 및 앱 규칙을 참조Razor하세요.
"ApplicationModel을(를) 수정하십시오."
다음 규칙은 애플리케이션 모델에 속성을 추가하는 데 사용됩니다.
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;
}
}
}
애플리케이션 모델 규칙은 MVC가 다음에서 추가되는 경우 옵션으로 적용됩니다.Startup.ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
속성은 컨트롤러 작업 내의 ActionDescriptor.Properties 컬렉션에서 액세스할 수 있습니다.
public class AppModelController : Controller
{
public string Description()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
}
ControllerModel 설명 수정
컨트롤러 모델에는 사용자 지정 속성도 포함될 수 있습니다. 커스텀 속성은 애플리케이션 모델에 지정된 동일한 이름의 기존 속성을 재정의합니다. 다음 규칙 특성은 컨트롤러 수준에서 설명을 추가합니다.
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;
}
}
}
이 규칙은 컨트롤러에서 특성으로 적용됩니다.
[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
public string Index()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
ActionModel 설명 수정
개별 작업에 별도의 특성 규칙을 적용하여 애플리케이션 또는 컨트롤러 수준에서 이미 적용된 동작을 재정의할 수 있습니다.
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;
}
}
}
컨트롤러 내의 작업에 이를 적용하면 컨트롤러 수준 규칙을 재정의하는 방법을 보여 줍니다.
[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"];
}
}
"ParameterModel을(를) 수정하십시오."
작업 매개 변수에 다음 규칙을 적용하여 해당 규칙을 수정할 수 있습니다 BindingInfo. 다음 규칙을 사용하려면 매개 변수가 경로 매개 변수여야 합니다. 쿼리 문자열 값과 같은 다른 잠재적 바인딩 원본은 무시됩니다.
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;
}
}
}
이 특성은 모든 작업 매개 변수에 적용될 수 있습니다.
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}";
}
}
모든 작업 매개 변수에 규칙을 적용하려면 MustBeInRouteParameterModelConvention에 MvcOptions을/를 Startup.ConfigureServices에 추가하세요.
options.Conventions.Add(new MustBeInRouteParameterModelConvention());
ActionModel 이름 수정
다음 규칙은 적용된 ActionModel 작업의 이름을 업데이트하도록 수정합니다. 새 이름은 특성에 대한 매개 변수로 제공됩니다. 이 새 이름은 라우팅에 사용되므로 이 작업 메서드에 도달하는 데 사용되는 경로에 영향을 줍니다.
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;
}
}
}
이 특성은 다음의 작업 메서드에 적용됩니다 HomeController.
// Route: /Home/MyCoolAction
[CustomActionName("MyCoolAction")]
public string SomeName()
{
return ControllerContext.ActionDescriptor.ActionName;
}
메서드 이름이 SomeName일지라도, 이 특성은 메서드 이름을 사용하는 MVC 규칙을 재정의하고, 작업 이름을 MyCoolAction로 바꿉니다. 따라서 이 작업에 도달하는 데 사용되는 경로는 .입니다 /Home/MyCoolAction.
비고
이 섹션의 이 예제는 기본적으로 기본 제공 ActionNameAttribute을 사용하는 것과 같습니다.
사용자 지정 라우팅 규칙
라우팅 방식이 작동하는 방법을 사용자 지정하는 데 IApplicationModelConvention를 사용합니다. 예를 들어, 다음 규칙은 컨트롤러의 네임스페이스를 경로에 통합하여 네임스페이스의 .를 경로의 /로 바꿉니다.
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
}
}
}
규칙은 다음의 옵션으로 추가됩니다.Startup.ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
팁 (조언)
다음 방법을 사용하여 미들웨어MvcOptions 에 규칙을 추가합니다.
{CONVENTION} 자리 표시자는 추가를 위한 규칙입니다.
services.Configure<MvcOptions>(c => c.Conventions.Add({CONVENTION}));
다음 예제에서는 컨트롤러 Namespace 이름이 있는 특성 라우팅을 사용하지 않는 경로에 규칙을 적용합니다.
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.";
}
}
}
애플리케이션 모델 사용량 WebApiCompatShim
ASP.NET Core MVC는 ASP.NET Web API 2의 다른 규칙 집합을 사용합니다. 사용자 지정 규칙을 사용하여 ASP.NET Core MVC 앱의 동작을 웹 API 앱의 동작과 일치하도록 수정할 수 있습니다. Microsoft는 이 목적을 위해 특별히 NuGet 패키지를 배송합니다.WebApiCompatShim
비고
ASP.NET Web API에서 마이그레이션하는 방법에 대한 자세한 내용은 ASP.NET Web API에서 ASP.NET Core로 마이그레이션을 참조하세요.
Web API 호환성 Shim을 사용하려면 다음을 수행합니다.
- 프로젝트에
Microsoft.AspNetCore.Mvc.WebApiCompatShim패키지를 추가합니다. -
AddWebApiConventions을 호출하여 MVC에 규약을 추가하십시오.
Startup.ConfigureServices
services.AddMvc().AddWebApiConventions();
shim에서 제공하는 규칙은 특정 특성이 적용된 앱의 일부에만 적용됩니다. 다음 네 가지 특성은 shim의 규칙에 따라 규칙을 수정해야 하는 컨트롤러를 제어하는 데 사용됩니다.
- UseWebApiActionConventionsAttribute
- UseWebApiOverloadingAttribute
- UseWebApiParameterConventionsAttribute
- UseWebApiRoutesAttribute
작업 규칙
UseWebApiActionConventionsAttribute는 HTTP 메서드를 이름에 따라 작업에 매핑하는 데 사용됩니다(예: Get가 HttpGet에 매핑됨). 특성 라우팅을 사용하지 않는 작업에만 적용됩니다.
오버로딩
UseWebApiOverloadingAttribute 은 WebApiOverloadingApplicationModelConvention 컨벤션을 적용하는 데 사용됩니다. 이 규칙은 OverloadActionConstraint을(를) 작업 선택 프로세스에 추가하여 후보 작업을 요청이 모든 필수 매개변수를 충족하는 것으로 제한합니다.
매개 변수 규칙
UseWebApiParameterConventionsAttribute 는 작업 규칙을 적용하는 WebApiParameterConventionsApplicationModelConvention 데 사용됩니다. 이 규칙은 작업 매개 변수로 사용되는 단순 형식이 기본적으로 URI에서 바인딩되는 반면 복합 형식은 요청 본문에서 바인딩되도록 지정합니다.
경로
UseWebApiRoutesAttribute는 WebApiApplicationModelConvention 컨트롤러 규약의 적용 여부를 제어합니다. 사용하도록 설정하면 이 관례를 사용하여 경로에 영역 대한 지원을 추가하고 컨트롤러가 api 영역에 있음을 나타냅니다.
호환성 패키지에는 규칙 집합 외에도 Web API에서 제공하는 기본 클래스를 대체하는 기본 클래스가 포함되어 System.Web.Http.ApiController 있습니다. 이렇게 하면 ASP.NET Core MVC에서 실행되는 동안 웹 API 컨트롤러가 ApiController을 상속하여 기능할 수 있습니다.
UseWebApi* 앞에 나열된 모든 특성이 기본 컨트롤러 클래스에 적용됩니다. 웹 ApiController API에 있는 속성, 메서드 및 결과 형식과 호환되는 형식을 노출합니다.
앱을 문서화하는 데 사용 ApiExplorer
애플리케이션 모델은 앱의 구조를 탐색하는 데 사용할 수 있도록 각 수준에서 ApiExplorerModel 속성을 노출합니다.
Swagger와 같은 도구를 사용하여 웹 API에 대한 도움말 페이지를 생성하는 데 사용할 수 있습니다. 이 ApiExplorer 속성은 앱 모델의 어떤 부분을 노출할지를 지정하기 위해 설정할 수 있는 IsVisible 속성을 제공합니다. 규칙을 사용하여 이 설정을 구성합니다.
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace AppModelSample.Conventions
{
public class EnableApiExplorerApplicationConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
application.ApiExplorer.IsVisible = true;
}
}
}
이 방법(및 필요한 경우 추가 규칙)을 사용하여 API 표시 유형은 앱 내의 모든 수준에서 사용하거나 사용하지 않도록 설정됩니다.
ASP.NET Core