Home > Sample chapters

Models, Views, and Controllers

It’s Not Just About MVC

As discussed earlier, there’s actually a lot more going on than just the models, views and controllers themselves in your solution. We’ll continue to explore these throughout the book, but here are some important ideas to have in the peripheral as you develop.

Middleware

Here is the secret about middleware in ASP.NET Core MVC: it’s pretty much all middleware. All of it! During application start-up you have the opportunity to load your configuration, configure your services, and then configure the request pipeline, which is where the concept of middleware is called into play. You can see this in the Configure method of the Startup class in the default project template.

Often, the description of middleware and the interpretation by the reader overcomplicates a fairly simple premise. The purpose of middleware is to allow an application to say, “Have each request processed by the following components in the order that I specify.” Middleware is a simplification over previous incarnations of similar functionality in ASP.NET, namely HTTP Modules and Handlers. Middleware replaces both with a common approach in a fashion that is easier to implement.

There are several pieces of middleware that ship publically to handle most scenarios that you need to cover during the execution of your application, both in lower level environments such as staging and QA, as well as in production:

  • Diagnostics: Provides exception handling and runtime helpers like database error pages and technical details to developers.

  • Static files: Allows a short-circuit of the request pipeline to return a file from disk.

  • Identity and Authentication: Allows applications to protect end points and assets of an application.

  • Routing: Resolves which controller and action should be executed based on the incoming path and parameters.

  • CORS: Handles injecting the correct headers for cross-origin resource sharing.

  • MVC itself: Usually at the end of the configured middleware pipeline as it consumes requests.

Each middleware component has the option to execute code before and after the next component in the chain, or to short-circuit the execution and return a response. The name middleware likely comes from the idea that you can execute a piece of software in the middle of something else, as shown in Figure 3.3. In this instance, you see a series of different requests that are handled by the various middleware components in the default project template. In some cases, the request is handled by the static files middleware, returning an asset in wwwroot. At other times, the request is allowed to pass all the way through to the MVC execution pipeline where your controller is created and you can return a view.

FIGURE 3-3

FIGURE 3-3 An illustration showing examples of different request types as handled by middleware

You can bring in other middleware from third parties, additional helpers that are provided by Microsoft, or you can write your own to handle cross-cutting concerns that are needed throughout your application. The middleware pipeline can also be branched based on paths or predicates to allow dynamic, flexible rules around processing requests.

Dependency Injection

There are many written volumes covering dependency injection, but we’ll recap the basics here for completeness.

Generally speaking, it’s likely going to be a good idea for your code to be obvious about the dependencies that it takes on. In C# you tend to do this by putting the components and services you need in your constructor, such that any creator of the class has to provide your dependencies for you.

Let’s consider the constructor of the HomeController class in Listing 3-4. The class requires that any time it is being created an instance of an ILogger implementation would be provided for it.

LISTING 3-4 The HomeController Class Constructor

public class HomeController{
  ILogger _logger
  public HomeController (ILogger logger)
  {
    _logger = logger;
  }
}

HomeController doesn’t need to know how to configure or create an ILogger, it doesn’t need to know where to log to, or how it is to be done. But from any point after instantiation, HomeController is now able to add valuable information to your log files as required. This one simple parameter on the constructor explicitly defines your requirements and is referred to as the Explicit Dependencies Principle.

For this controller to be created by the pipeline, you need to have something in the runtime aware of how to resolve the ILogger requirement. You configure these services and components in a container, and then these types of dependencies are injected for you into the constructors at runtime. And voila, dependency injection! Being a broader topic, and also by virtue of ASP.NET Core MVC introducing some new ideas for Dependency I njection (DI), we’re going to take a deeper look at the idea of inverting control in Chapter 14, “Dependency Injection,” where we’ll also explore what is required when replacing the default container.

Other Gems

ASP.NET Core MVC contains some great improvements over previous versions and we are going to explore them throughout the book.

  • Configuration and Logging: Long considered afterthoughts in the .NET space, these critical application aspects have been revamped, simplified, and made into first-class citizens. Read more about these in Chapter 12, “Configuration and Logging.”

  • Tag Helpers: Along with a few other aspects of simplifying front end development, in Chapter 18, “Reusable Components,” we’ll examine Tag Helpers and how they more closely resemble the HTML we’re trying to return to the client.

  • Identity: A user is more than just a name and a password. In Chapter 13, “Identity, Security & Rights,” we’ll explore the new features, uses, and components around security and rights management in ASP.NET Core MVC.