[Controller] and [NonController] attributes in ASP.NET Core MVC

One of the late additions before the RTM release of ASP.NET Core MVC was the introduction of the [Controller] attribute, and its counterpart, [NonController], which were added in RC2.

Together, they allow you to more specifically control which classes should be considered by the framework to be controllers (or controller candidates) and which shouldn’t. They also help you avoid the nasty hacks we needed to do in i.e. ASP.NET Web API to opt out from the “Controller” suffix in the name.

Let’s have a look.

[Controller] vs [NonController] and the built-in conventions

ASP.NET Core MVC supports the concept of POCO controllers so you no longer need to inherit from the base Controller class in order to create the your HTTP endpoints.

If you choose to use POCO controllers, your class will be considered to be a valid controller simply if it has a Controller suffix in the class name.

So these are the two fundamental prerequisites when authoring MVC controllers:
– inherit from Controller base class
– or use a Controller suffix in the name

As a result, the following two controller declarations will work out of the box:

Now what’s more interesting, is what happens if you define a controller by inheriting from the base Controller, but you omit the Controller suffix in the name?

Well, turns out this is also correct. The reason why this can work, is that the base class Controller (or – to be more specific, it’s own base class, called ControllerBase), is decorated with the [Controller] attribute, which indicates that the entire inheritance tree should be considered as valid MVC controllers.

Another possibility is that you’d have a POCO controller, that doesn’t have the Controller suffix in the name. That is shown below:

This will not work out of the box, and this is where you need to use the [Controller] attribute.

Just like it is the case with the built-in Controller type, you could also decorate a base class with a [Controller] attribute and all the inheriting classes would be considered controllers then.

There is also a possibility where you’d have a class, which uses the Controller suffix in the name, but it should not become an MVC POCO controller. That’s where you need to opt out from the controller scan, by applying the [NonController] attribute.

Finally, what’s also worth mentioning, is that [NonController] will always have higher precendence than [Controller]. In fact, if the [NonController] appears anywhere in the class hierarchy, the type or its descendants will never be considered controller candidates anymore.