[ASP.NET Core MVC Pipeline] Controller Initialization – Action Selection

So, we just finished looking at the Routing Middleware, and that also completes our walk-through the Middleware Pipeline! What happens next? Now we enter the realm of the Controller Initialization, and the first thing we need to do is the Action Selection. Let’s revisit our MVC Core Pipeline flow.

The ASP.NET Core MVC Pipeline
The ASP.NET Core MVC Pipeline

We will now focus on the green part of our pipeline, the Controller Initialization.

Controller Initialization
Controller Initialization

The objective of the process in the green box is:

  1. Find the most suitable Action in the application for that request
  2. Call the Controller Factory informing the required Action
  3. Get an instance of a Controller from the Controller Factory

That is all it does, and it is a very important job 🙂 But, how can we interfere with this process? The first thing we can do is add some rules to make the Action Selection behave as we want it to.

The easiest way

You don't have to customize everything
You don’t have to customize everything

It’s true! You probably already used some alternatives to bend the process of Action Selection towards your objectives. The most common method is to use the Verb Attributes. Let’s imagine you want to create 4 actions in a single controller and each of them will respond to a different HTTP Verb:

What is wrong with this code? All the methods claim the same action path on the route, and the Action Selector has no good way to define which one to call! What will happen when we try to access the /index route?

Ambiguous Exception
Ambiguous Exception

Ambiguous Exception! and that happens, as you can see in the underscored line, because the framework does not have enough information to decide which one is the best candidate action, and that is where we can use a MethodSelectorAttribute:

Now the framework will know the best action to choose based on the HTTP Verb of the Request 🙂

That code exemplifies the kind of intervention that we can do in the process of choosing the most fitting Action Method. But, what if we want to change this behavior in a way that is specific to some kind of logic that we envisioned? That is when you should think about adding an Action Constraint.

What is an Action Constraint?

An Action Constraint is a way that we have to tell the Action Selection process that some method should be a better candidate than the other options for that request. It is really that simple. An action constraint is a class that implements the following Interface:

The Order property will help you define the priority in which that constraint must be evaluated and the Accept method is where the true logic is implemented. Whenever an ActionConstraint is evaluated and the return of the Accept method is TRUE, then it will tell the Action Selection process that this Action is a better suitable match for the request.

Customizing the Action Selection – Custom Action Constraint

Now let’s implement our own IActionConstraint and force the Action Selection process to work as we want it to. Let’s imagine a scenario where we want to serve specific content to our users who access our application through a Mobile Browser, and we want to handle that on the back-end, as we really will serve different data to this users. In this situation we have the following Action Methods:

That would, again, give us the AmbiguousException because, as it is, is impossible to the framework to choose a better Action between those two, so what can we do to help? Let’s implement our action constraint:

I know, I know… there are sure better ways to implement this behavior and that not fool-proof at all, but it is enough for our intents. We set the Order property of our Action Constraint to “0” so it will be one of the first to be evaluated by the framework, and the implementation of our Accept Method returns true if the request’s user-agent container either “Android” or “iPhone” in its value.

So, how to hookup this component to our pipeline? Easy enough:

Ha! Simple, isn’t it?

Results

Default Content
Default Content

When accessing through a common browser, you are going to be redirected to the default implementation of our View…

Mobile Content
Mobile Content

…and when accessed through a Mobile Browser, you will be presented with the specific implementation of our View. Cool, right?

This is one of my favorite pluggable components in the entire framework pipeline. It doesn’t feel too much invasive, and it can help us bend the flow of the request in a very useful way!

What do you think of it? Can we think of a way to use it on your applications?

Source:

The ASP.NET Core MVC Pipeline

Hallo Iedereen 🙂
I decided to start a series of posts about custom components for the ASP.NET Core MVC Pipeline.

Most of you should know by now that ASP.NET Core was mostly redesigned to be more modular, extensible and to deal with the ‘platform agnostic’ nature of the new framework. This redesign also allows us to customize the way every request is processed, adding custom components in each step of the pipeline.

The ASP.NET Core MVC Pipeline

The ASP.NET Core MVC Pipeline
The ASP.NET Core MVC Pipeline

The idea is to have one post for each of the small blocks on the pipeline, precisely because it is possible to hook up your custom code in any of those points.

I’ll start by providing a brief overview of which is the role of each block on the pipeline:

Middleware Pipeline

Middleware Pipeline
Middleware Pipeline

The middleware pipeline is the entry point for each request in an HTTP Request, it is basically a stack of components that can execute some logic and decide whether to pass the request to the next middleware, or to send the response back to the client.

Routing Middleware

The routing middleware is just one of many that can be used by the ASP.NET Core but is of major importance to the Core MVC Pipeline. The reason for this it that this is the Middleware that ‘captures’ an incoming request and really starts the MVC Pipeline. If an incoming request url does not match any registered Route the request is passed onward to the next Middleware, ignoring the MVC Pipeline, but when the request url matches a known route, that is when the MVC Pipeline really begins.

Controller Initialization

Controller Initialization
Controller Initialization

Once a route is found by the Routing middleware, the next step is to find a controller that matches the route and instantiate it. The process of finding the best suitable Controller and Action for a Route can also be customized.

Action Execution

Action Execution
Action Execution

Now we are in the core of what really is the MVC pattern. The Action Execution is the process that will really process the incoming request and, after that, generate a Result. This is also the process where we can hook up most of our components.

Model Binding

One of the greatest features on the MVC Framework is the ability to bind request data to POCO Objects. I’ll try to explain a bit about how the standard Models Binders work, and how you can create your own Model Binder.

Filters

Filters are components that can be injected at many stages of the Action Execution and that will allow us to define behaviors that we want in our Actions, but that are not necessarily part of the LOB Logic.

Action Result

Finally, the action result is the last step of the Action Execution, and it involves basically to create a ‘Result’ type that will be processed by the Result Execution.

Result Execution

Result Execution
Result Execution

And the last step in the Core MVC Pipeline has arrived! Here is where our ‘Result’ will be analysed and processed accordingly. Here we can also inject some filters before and after our processing, allowing us to change the way the result will be processed.

Where do we start?

From the beginning! Of course 🙂 We will start creating a Custom Middleware that will be executed before the Routing Middleware.

The first post will be up very soon!

Tot ziens! (And I just spent all my Dutch in this post)

Source: