The default conventions of ASP.NET Core MVC allow us to easily construct applications without having to worry about the minutiae of wiring up the “how-to” parts that are required in nearly every application that will be built. There are times when these conventions do not meet your application needs, but you can instruct the framework to work the way you need it to by building your own.
If you’ve worked inside of the MVC Framework you’ve either explicitly noticed or been implicitly subjected to some of the conventions at work. These include things like:
- Names of methods in the startup class
- Project layout
- View search locations
- Routing expressions as they relate to controller and action names
- Web API exposing actions that are named as HTTP verbs
These conventions work to remove some of the effort we need to get our application running. Some of them are locked in - we can’t change the names of methods that are invoked in the startup class, for instance, as there is an explicit search for
ConfigureServices - but others can be ammended, removed, and replaced on our whim.
There are four categories of conventions that we’re going to briefly discuss here:
|Application (Widest net)||
||Provides access to application-wide conventions, allowing you to iterate over each of the levels below.|
||Conventions that are specific to a controller, but also allows you to evaluate lower levels.|
||Changes to action-level conventions can be made here, as well as on any parameters of the actions.|
|Parameter (Smallest scope)||
||Specific to parameters only.|
As your application loads it will use any conventions that you have added starting at the outter-most field of view, application conventions, then working it’s way in through controller and action conventions to parameter conventions. In this way, the most specific conventions are applied last, meaning there is a caveat that if you add a parameter convention by using
IControllerModelConvention then it could be overwritten by any
IParameterModelConvention, regardless of the order in which you add the conventions to the project. This is different from middleware, in a sense, because the order of conventions only applies within the same level, and there is a priority on level that you can’t adjust.
I wanted to build a convention that celebrated how great rabbits were at math, specifically, multiplication. You know those rabbits! What I did first was to create an interface:
…so that I could use it in an attribute:
…which allowed me to apply the attribute to my controller:
…so that I could leverage the attribute in my convention:
Now, the great math capabilities of bunnies are available! I loop through all the actions on my controller and create a cloned version of the action with the prefix
Bunny. So there will be an
Index action and a
BunnyIndex and so forth at runtime. Now, you may think that this isn’t too relevant at first glance, so I’ll leave it as an excercise to the reader to think about how Web API actions might be handled by convention when you have action names that are verbs.
Wiring up the convention is easy…just add it to the conventions collection when you’re adding MVC in the
ConfigureServices method in
Here are some great resources that will help you explore other uses of these interfaces.
Filip Wojcieszyn’s Posts and Community Contributions
Steve Smith’s article on feature folders
As you can see, you are not locked into the default behaviours of ASP.NET Core MVC, and you have many surface areas acting as cusomization points for you to exploit.