ASP.NET Core MVC Application Model – Part I

EDIT 03/08/2016: this post was updated to reflect naming changes from MVC 6 to ASP.NET Core MVC. All the contents still apply.


On my previous posts about routing on ASP.NET 5 I mentioned how action descriptors are used to build routes for attribute routing. Action descriptors represent the HTTP endpoints on the application and, as expected, they are also used when selecting an action for a given request.

The collection of action descriptors that are used by the framework is obtained via a set of IActionDescriptorProvider. While it is possible to add/replace IActionDescriptorProviders, the built-in implementation includes another mechanism to enable customization of action descriptors on most scenarios: the ApplicationModel.

The application model is a representation of the application components discovered by the framework, namely controllers and their actions. As illustrated below, this model includes a lot of metadata on the different components.

application_model

The application model is also created by a set of providers, represented by the IApplicationModelProvider interface. Again, it’s not very likely that you need to replace/extend these providers, since the application model is made available for customization (more on this soon). It’s also worth pointing that, in order to build the application model, the framework needs to find the controller types available on the application. The lookup is based on IControllerTypeProvider and can also be configured as needed. This post describes controller discovery in more detail.

Back to the application model diagram, lets go into some of the types and how they are used by the default application model provider:

  • ControllerModel – represents a controller that was discovered by the application model provider. An instance of this class is created for each controller that is discovered by the aforementioned IControllerTypeProvider. This is also when the controller names are defined.
  • ActionModel – represents an action of a controller. An instance of this class is created for each eligible action on a controller. There are multiple requirements for a method to become an action, such as being public, non-abstract and not inherited from object.
  • IFilterMetadata – marker interface to signal a filter. Filters can be applied at application (global), controller or action level. The default application model provider searches for filters metadata on the custom attributes of controller and action types. The final set of filters on each action is assembled later on, when building the action descriptors.
  • IRouteConstraintProvider – also specified via custom attributes, this interface can be used to specify constraints for a given route value (e.g. area=xpto).
  • IActionConstraintMetadata – marker interface for action constraints, i.e. types that will help determine if an action is suitable for a given HTTP request. I’ll exemplify their usage on the second post of this series.

I previously mentioned that the application model is a means of customizing action descriptors, but that’s not completely accurate. In fact, that customization is supported by the default IActionDescriptorProvider using application model conventions, which are applied to the application model:

internal protected IEnumerable<ControllerActionDescriptor> GetDescriptors()
{
    var applicationModel = BuildModel();
    ApplicationModelConventions.ApplyConventions(applicationModel, _conventions);
    return ControllerActionDescriptorBuilder.Build(applicationModel);
}

As shown on the snippet above, a set of conventions is applied to the application model before it is used to build the final action descriptors. A convention is represented by the IApplicationModelConvention interface and has access to the whole application model for modification:

public interface IApplicationModelConvention
{
  void Apply(ApplicationModel application);
}

One might ask why the application model was introduced, instead of having the developers directly customize action descriptors. Despite not being sure about the reasons, I’d say the ASP.NET team wanted to provide a customization model that is closer to how a developer organizes the application (e.g. controllers that contain actions). The final action descriptors are more complex and there’s a lot of plumbing to be done to create them that probably shouldn’t surface to the developer. For instance, a single ActionModel might result on multiple ActionDescriptors, depending on attribute routing. The application model is simpler and easier to modify, leaving all the final hard work to the framework.

On the following post I’ll bring up some code exemplifying the usage of conventions and some other interfaces that are present on the application model. Stay tuned!

Advertisement

1 thought on “ASP.NET Core MVC Application Model – Part I

  1. Pingback: Customizing ASP.NET Core MVC: filters, constraints and conventions | Luís Gonçalves

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s