ASP.NET Core のアプリケーション モデルの使用Work with the application model in ASP.NET Core

作成者: Steve SmithBy Steve Smith

ASP.NET Core MVC では、MVC アプリのコンポーネントを表すアプリケーション モデルを定義できます。ASP.NET Core MVC defines an application model representing the components of an MVC app. このモデルを読み、操作し、MVC 要素の動作を変更することができます。You can read and manipulate this model to modify how MVC elements behave. 既定で、MVC には、どのクラスがコントローラーとして考慮されるか、それらのクラスのどのメソッドがアクションであるか、パラメーターおよびルーティングがどのように動作するかについて、特定の規則があります。By default, MVC follows certain conventions to determine which classes are considered to be controllers, which methods on those classes are actions, and how parameters and routing behave. この動作をアプリのニーズに合うようにカスタマイズして、独自の規則を作成し、それらをグローバルにまたは属性として適用することができます。You can customize this behavior to suit your app's needs by creating your own conventions and applying them globally or as attributes.

モデルおよびプロバイダーModels and Providers

ASP.NET Core MVC アプリケーション モデルには、MVC アプリケーションを表現する、抽象インターフェイスと具象実装クラスの両方が含まれています。The ASP.NET Core MVC application model include both abstract interfaces and concrete implementation classes that describe an MVC application. このモデルは、既定の規則に従ってアプリのコントローラー、アクション、アクション パラメーター、ルート、およびフィルターを検出する MVC の結果です。This model is the result of MVC discovering the app's controllers, actions, action parameters, routes, and filters according to default conventions. アプリケーション モデルを使用すると、既定の MVC の動作とは異なる規則を使用するようアプリを変更することができます。By working with the application model, you can modify your app to follow different conventions from the default MVC behavior. パラメーター、名前、ルート、およびフィルターは、すべてアクションおよびコントローラーの構成データとして使用されます。The parameters, names, routes, and filters are all used as configuration data for actions and controllers.

ASP.NET Core MVC アプリケーション モデルの構造は、次のとおりです。The ASP.NET Core MVC Application Model has the following structure:

  • ApplicationModelApplicationModel
    • コントローラー (ControllerModel)Controllers (ControllerModel)
      • アクション (ActionModel)Actions (ActionModel)
        • パラメーター (ParameterModel)Parameters (ParameterModel)

このモデルでは、各レベルで、共通の Properties コレクションにアクセスできます。下位レベルでは、階層の上位レベルで設定されたプロパティ値にアクセスしたり上書きしたりできます。Each level of the model has access to a common Properties collection, and lower levels can access and overwrite property values set by higher levels in the hierarchy. このプロパティは、アクションの作成時、ActionDescriptor.Properties に保存されます。The properties are persisted to the ActionDescriptor.Properties when the actions are created. そして要求の処理時に、規則によって追加または変更されたすべてのプロパティに、ActionContext.ActionDescriptor.Properties を介してアクセスできます。Then when a request is being handled, any properties a convention added or modified can be accessed through ActionContext.ActionDescriptor.Properties. フィルターやモデル バインダーなどをアクションごとに構成するのに、プロパティを使用するのはよい方法です。Using properties is a great way to configure your filters, model binders, etc. on a per-action basis.

注意

アプリのスタートアップが完了している場合、ActionDescriptor.Properties コレクションは (書き込みに) スレッド セーフではありません。The ActionDescriptor.Properties collection isn't thread safe (for writes) once app startup has finished. このコレクションにデータを安全に追加するには、規則が最善の方法です。Conventions are the best way to safely add data to this collection.

IApplicationModelProviderIApplicationModelProvider

ASP.NET Core MVC は、IApplicationModelProvider インターフェイスによって定義されるプロバイダー パターンを使用して、アプリケーション モデルを読み込みます。ASP.NET Core MVC loads the application model using a provider pattern, defined by the IApplicationModelProvider interface. このセクションでは、このプロバイダーがどのように機能するかについての、いくつかの内部実装に関する詳細を説明します。This section covers some of the internal implementation details of how this provider functions. これは高度なトピックです。アプリケーション モデルを活用するアプリのほとんどでは、規則を使用してアプリケーション モデルを活用する必要があります。This is an advanced topic - most apps that leverage the application model should do so by working with conventions.

IApplicationModelProvider インターフェイスの実装は、その Order プロパティに応じて、昇順で OnProvidersExecuting を呼び出して互いを "ラップ" します。Implementations of the IApplicationModelProvider interface "wrap" one another, with each implementation calling OnProvidersExecuting in ascending order based on its Order property. 次いで、OnProvidersExecuted メソッドが逆順で呼び出されます。The OnProvidersExecuted method is then called in reverse order. このフレームワークでは、次のいくつかのプロバイダーが定義されます。The framework defines several providers:

1 番目 (Order=-1000):First (Order=-1000):

次 (Order=-990):Then (Order=-990):

注意

2 つのプロバイダーの Order の値が同じである場合、順序は定義されていないため、これには依存しないようにする必要があります。The order in which two providers with the same value for Order are called is undefined, and therefore shouldn't be relied upon.

注意

IApplicationModelProvider は、フレームワークの作成者が拡張する高度な概念です。IApplicationModelProvider is an advanced concept for framework authors to extend. 一般に、規則やフレームワークを使う必要があるアプリは、プロバイダーを使う必要があります。In general, apps should use conventions and frameworks should use providers. 重要な違いは、プロバイダーは常に規則の前に実行されるということです。The key distinction is that providers always run before conventions.

DefaultApplicationModelProvider は ASP.NET Core MVC で使用される多数の既定の動作を確立します。The DefaultApplicationModelProvider establishes many of the default behaviors used by ASP.NET Core MVC. 次の役割があります。Its responsibilities include:

  • コンテキストにグローバル フィルターを追加するAdding global filters to the context
  • コンテキストにコントローラーを追加するAdding controllers to the context
  • アクションとしてパブリック コントローラー メソッドを追加するAdding public controller methods as actions
  • コンテキストにアクション メソッド パラメーターを追加するAdding action method parameters to the context
  • ルートおよびその他の属性を適用するApplying route and other attributes

いくつかの組み込みの動作は、DefaultApplicationModelProvider によって実装されます。Some built-in behaviors are implemented by the DefaultApplicationModelProvider. このプロバイダーは、ActionModelPropertyModel、および ParameterModel インスタンスを代わりに参照する、ControllerModel を構築する役割があります。This provider is responsible for constructing the ControllerModel, which in turn references ActionModel, PropertyModel, and ParameterModel instances. DefaultApplicationModelProvider クラスは、今後変更する可能性がある変更される、内部フレームワークの実装についての詳細です。The DefaultApplicationModelProvider class is an internal framework implementation detail that can and will change in the future.

AuthorizationApplicationModelProvider は、AuthorizeFilter 属性および AllowAnonymousFilter 属性に関連付けられた動作を適用します。The AuthorizationApplicationModelProvider is responsible for applying the behavior associated with the AuthorizeFilter and AllowAnonymousFilter attributes. これらの属性については、こちらを参照してくださいLearn more about these attributes.

CorsApplicationModelProvider は、IEnableCorsAttribute および IDisableCorsAttribute および DisableCorsAuthorizationFilter に関連付けられた動作を実装します。The CorsApplicationModelProvider implements behavior associated with the IEnableCorsAttribute and IDisableCorsAttribute, and the DisableCorsAuthorizationFilter. CORS の詳細については、こちらを参照してください.Learn more about CORS.

規約Conventions

このアプリケーション モデルでは、モデルまたはプロバイダー全体をオーバーライドするよりも簡単に、モデルの動作をカスタマイズできる、規則の抽象化を定義できます。The application model defines convention abstractions that provide a simpler way to customize the behavior of the models than overriding the entire model or provider. これらの抽象化は、アプリの動作の変更に推奨されます。These abstractions are the recommended way to modify your app's behavior. 規則では、動的にカスタマイズすることが可能なコードを記述することができます。Conventions provide a way for you to write code that will dynamically apply customizations. フィルターでは、フレームワークの動作を変更できるのに対して、カスタマイズではアプリ全体がどのように結合されるかを制御できます。While filters provide a means of modifying the framework's behavior, customizations let you control how the whole app is wired together.

次の規則があります。The following conventions are available:

規則は、規則を MVC オプションを追加したり、Attribute を実装してそれらをコントローラー、アクション、またはアクション パラメーターに適用したりすることによって適用します (Filters と類似しています)。Conventions are applied by adding them to MVC options or by implementing Attributes and applying them to controllers, actions, or action parameters (similar to Filters). フィルターとは異なり、規則は、各要求の一部としてではなく、アプリの起動時にのみ実行されます。Unlike filters, conventions are only executed when the app is starting, not as part of each request.

サンプル:ApplicationModel を変更するSample: Modifying the ApplicationModel

次の規則は、アプリケーション モデルにプロパティを追加するために使用します。The following convention is used to add a property to the application model.

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 が StartupConfigureServices に追加されるときに、オプションとしてが適用されます。Application model conventions are applied as options when MVC is added in ConfigureServices in Startup.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Conventions.Add(new ApplicationDescription("My Application Description"));
        options.Conventions.Add(new NamespaceRoutingConvention());
        //options.Conventions.Add(new IdsMustBeInRouteParameterModelConvention());
    });
}

プロパティは、コントローラー アクション内の ActionDescriptor プロパティ コレクションからアクセスできます。Properties are accessible from the ActionDescriptor properties collection within controller actions:

public class AppModelController : Controller
{
    public string Description()
    {
        return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
    }
}

サンプル:ControllerModel の説明を変更するSample: Modifying the ControllerModel Description

前の例のように、コントローラー モデルを変更して、カスタム プロパティを含めることもできます。As in the previous example, the controller model can also be modified to include custom properties. これらは、アプリケーション モデルで指定した同じ名前の既存のプロパティをオーバーライドします。These will override existing properties with the same name specified in the application model. 次の規則属性では、コントローラー レベルで説明が追加されます。The following convention attribute adds a description at the controller level:

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;
        }
    }
}

この規則は、コントローラーの属性として適用されます。This convention is applied as an attribute on a controller.

[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
    public string Index()
    {
        return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
    }

"description" プロパティは、前の例と同じ方法でアクセスされます。The "description" property is accessed in the same manner as in previous examples.

サンプル:ActionModel の説明を変更するSample: Modifying the ActionModel Description

既にアプリケーションまたはコントローラー レベルに適用されている動作をオーバーライドして、個別のアクションに別の属性規則を適用することができます。A separate attribute convention can be applied to individual actions, overriding behavior already applied at the application or controller level.

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;
        }
    }
}

コントローラーのアクションにこれを適用している前の例は、コントローラー レベルで規則をオーバーライドする方法を示しています。Applying this to an action within the previous example's controller demonstrates how it overrides the controller-level convention:

[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 を変更するSample: Modifying the ParameterModel

次の規則をアクション パラメーターに適用して、BindingInfo を変更することができます。The following convention can be applied to action parameters to modify their BindingInfo. 次の規則では、パラメーターはルート パラメーターである必要があります。その他のバインディング ソースとなる可能性のあるものは (クエリ文字列の値など) 無視されます。The following convention requires that the parameter be a route parameter; other potential binding sources (such as query string values) are ignored.

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;
        }
    }
}

この属性は、任意のアクション パラメーターに適用できます。The attribute may be applied to any action parameter:

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}";
    }
}

サンプル:ActionModel 名を変更するSample: Modifying the ActionModel Name

次の規則は、ActionModel が適用されるアクションの名前を更新してそれを変更します。The following convention modifies the ActionModel to update the name of the action to which it's applied. この新しい名前は、属性にパラメーターとして提供されます。The new name is provided as a parameter to the attribute. この新しい名前はルーティングによって使用されるので、このアクション メソッドに到達するのに使用されるルートに影響します。This new name is used by routing, so it will affect the route used to reach this action method.

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 のアクション メソッドに適用されます。This attribute is applied to an action method in the HomeController:

// Route: /Home/MyCoolAction
[CustomActionName("MyCoolAction")]
public string SomeName()
{
    return ControllerContext.ActionDescriptor.ActionName;
}

メソッド名は SomeName ですが、このメソッド名を使用する MVC 規則をこの属性はオーバーライドし、アクション名を MyCoolAction に置換します。Even though the method name is SomeName, the attribute overrides the MVC convention of using the method name and replaces the action name with MyCoolAction. したがって、このアクションに到達するのに使用されるルートは、/Home/MyCoolAction です。Thus, the route used to reach this action is /Home/MyCoolAction.

注意

この例は、基本的に、組み込みの ActionName 属性を使用するのと同じです。This example is essentially the same as using the built-in ActionName attribute.

サンプル:カスタム ルーティング規則Sample: Custom Routing Convention

IApplicationModelConvention を使用して、ルーティングの動作をカスタマイズできます。You can use an IApplicationModelConvention to customize how routing works. たとえば、次の規則は、名前空間の . をルートの / に置き換えてコントローラーの名前空間をそのルートに組み込みます。For example, the following convention will incorporate Controllers' namespaces into their routes, replacing . in the namespace with / in the route:

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
        }
    }
}

この規則は、スタートアップのオプションとして追加されています。The convention is added as an option in Startup.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Conventions.Add(new ApplicationDescription("My Application Description"));
        options.Conventions.Add(new NamespaceRoutingConvention());
        //options.Conventions.Add(new IdsMustBeInRouteParameterModelConvention());
    });
}

ヒント

services.Configure<MvcOptions>(c => c.Conventions.Add(YOURCONVENTION)); を使用し、MvcOptions にアクセスして、ミドルウェアに規則を追加できます。You can add conventions to your middleware by accessing MvcOptions using services.Configure<MvcOptions>(c => c.Conventions.Add(YOURCONVENTION));

このサンプルでは、コントローラー名に "Namespace" が含まれる、属性のルーティングを使用していないルートにこの規則は適用されます。This sample applies this convention to routes that are not using attribute routing where the controller has "Namespace" in its name. この規則は、次のコントローラーによって使用されます。The following controller demonstrates this convention:

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 でのアプリケーション モデルの使用法Application Model Usage in WebApiCompatShim

ASP.NET Core MVC と ASP.NET Web API 2 とでは使用する規則のセットが異なります。ASP.NET Core MVC uses a different set of conventions from ASP.NET Web API 2. カスタム規則を使用すると、Web API アプリの動作と一致するように、ASP.NET Core MVC アプリの動作を変更できます。Using custom conventions, you can modify an ASP.NET Core MVC app's behavior to be consistent with that of a Web API app. Microsoft では、この目的専用に WebApiCompatShim を出荷しています。Microsoft ships the WebApiCompatShim specifically for this purpose.

注意

ASP.NET Web API からの移行に関するページをご覧ください。Learn more about migration from ASP.NET Web API.

Web API Compatibility Shim を使用するには、プロジェクトにパッケージを追加し、StartupAddWebApiConventions を呼び出して MVC に規則を追加する必要があります。To use the Web API Compatibility Shim, you need to add the package to your project and then add the conventions to MVC by calling AddWebApiConventions in Startup:

services.AddMvc().AddWebApiConventions();

Shim が提供するこの規則は、それに特定の属性が適用されたアプリの一部にのみ適用されます。The conventions provided by the shim are only applied to parts of the app that have had certain attributes applied to them. 次の 4 つの属性は、Shim の規則でどのコントローラーが規則を変更する必要があるかを制御するために使用されます。The following four attributes are used to control which controllers should have their conventions modified by the shim's conventions:

アクション規則Action Conventions

UseWebApiActionConventionsAttribute は、名に基づいてアクションに HTTP メソッドをマップするために使用されます (たとえば、GetHttpGet にマップされます)。The UseWebApiActionConventionsAttribute is used to map the HTTP method to actions based on their name (for instance, Get would map to HttpGet). これは、属性のルーティングを使用しないアクションにのみ適用されます。It only applies to actions that don't use attribute routing.

オーバーロードOverloading

UseWebApiOverloadingAttribute は、WebApiOverloadingApplicationModelConvention 規則を適用するために使用されます。The UseWebApiOverloadingAttribute is used to apply the WebApiOverloadingApplicationModelConvention convention. この規則は、アクションの選択プロセスに OverloadActionConstraint を追加します。これによって、候補のアクションは、要求で省略可能でないすべてのパラメーターが満たされるものに制限されます。This convention adds an OverloadActionConstraint to the action selection process, which limits candidate actions to those for which the request satisfies all non-optional parameters.

パラメーター規則Parameter Conventions

UseWebApiParameterConventionsAttribute は、WebApiParameterConventionsApplicationModelConvention アクション規則を適用するために使用されます。The UseWebApiParameterConventionsAttribute is used to apply the WebApiParameterConventionsApplicationModelConvention action convention. この規則では、アクション パラメーターとして使用される単純な型は、要求本文からバインドされる複雑な型に対し、既定で URI からバインドされることが指定されます。This convention specifies that simple types used as action parameters are bound from the URI by default, while complex types are bound from the request body.

ルートRoutes

UseWebApiRoutesAttribute は、WebApiApplicationModelConvention コントローラー規則が適用されるかどうかを制御します。The UseWebApiRoutesAttribute controls whether the WebApiApplicationModelConvention controller convention is applied. これが有効な場合、この規則はルートに領域のサポートを追加するために使用されます。When enabled, this convention is used to add support for areas to the route.

互換パッケージには、規則のセットに加え、Web API によって提供されるものの代わりとなる System.Web.Http.ApiController 基底クラスが含まれます。In addition to a set of conventions, the compatibility package includes a System.Web.Http.ApiController base class that replaces the one provided by Web API. これにより、Web API 用に記述され、その ApiController から継承されたコントローラーが、ASP.NET Core MVC での実行中に、設計どおりに動作するようにすることを可能にします。This allows your controllers written for Web API and inheriting from its ApiController to work as they were designed, while running on ASP.NET Core MVC. この基本コントローラー クラスは、前述のすべての UseWebApi* 属性で修飾されています。This base controller class is decorated with all of the UseWebApi* attributes listed above. ApiController では、Web API にあるものと互換性のあるプロパティ、メソッド、および結果の型が公開されます。The ApiController exposes properties, methods, and result types that are compatible with those found in Web API.

アプリをドキュメント化するための ApiExplorer の使用Using ApiExplorer to Document Your App

このアプリケーション モデルは、アプリの構造をスキャンするために使用できる ApiExplorer プロパティを各レベルで公開します。The application model exposes an ApiExplorer property at each level that can be used to traverse the app's structure. これは、Swagger などのツールを使用して、Web API のヘルプ ページを生成するために使用できます。This can be used to generate help pages for your Web APIs using tools like Swagger. ApiExplorer プロパティは、アプリのモデルのどの部分を公開するか指定するために設定できる IsVisible プロパティを公開します。The ApiExplorer property exposes an IsVisible property that can be set to specify which parts of your app's model should be exposed. この設定は、次の規則を使用して構成できます。You can configure this setting using a convention:

using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace AppModelSample.Conventions
{
    public class EnableApiExplorerApplicationConvention : IApplicationModelConvention
    {
        public void Apply(ApplicationModel application)
        {
            application.ApiExplorer.IsVisible = true;
        }
    }
}

このアプローチを使用すると (必要に応じて追加の規則が必要)、アプリ内で任意のレベルで API の可視性を有効または無効にできます。Using this approach (and additional conventions if required), you can enable or disable API visibility at any level within your app.