Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Why(s) and How(s) of ASP.NET MVC: Part 3

0.00/5 (No votes)
19 Dec 2013 1  
ASP.NET MVC controller and routing fundamental ideas, advantages, and validating controllers.

Introduction

Picking up from our last discussion from part 2, I hope by now we have got an idea on the Model. Now we can move to our next topic, which is Controllers and my personal favorite, Routing. I like to cover Controllers and Routing in this same post as I believe it will be more convenient to readers. As usual I like to skip the how to, and rather to focus on the why.

Why Controllers 

The controller's job is to avoid request chaos. Without the controller things get messy, and this is true not just for MVC, but in real life also. Now think about a real life example. In an airport there are hundreds of flights using runways, but does the airport accommodate individual runways for individual flights? No, flights share the same runway. Now think if there is no control over which flight will use runways and when, and things will be just like in this illustration:

To avoid such a mess, airports requires ATC (Air Traffic Control). As Wiki says:

The primary purpose of ATC is to prevent collisions, organize and expedite the flow of traffic, and provide information and other support for pilots.

Similar to ATC, we have a Controller in MVC. The Controller controls the application logic and acts as the coordinator between the view and the model.

This process is pretty simple. When the request from the user lands in the MVC framework, it first goes to the controller. The Controller's responsibility at this point is to determine which model should be called, and then call the appropriate function within that model. After calling the function, it will catch the result.

Now the question could be is this new concept introduced only in MVC? The answer is no. If you read the first part, our very known web forms uses a similar concept. Web forms use the Page Controller pattern that handles all HTTP requests directed at a specific web page. This is where MVC tops traditional web forms by structuring the control flow into controllers to make the application logic simple and testable.

When we are talking about controllers handling user requests, this is where Routing kicks in. Routing is pre-configured in an MVC application that invokes the action methods defined in the controller.

Routing and Controller

You have probably seen a highway shield or route marker used by travelers for identifying, navigating, and organizing routes within a county/state.

Just like a highway shield which directs travelers, ASP.NET routing directs incoming requests to the appropriate controller actions.

As the name implies, routing is a handler which is in reality a class that processes the requests, such as a controller in an MVC application. The ASP.NET Routing module is responsible for mapping incoming browser requests to a particular MVC controller actions.

Routing uses URL patterns to identify proper controllers as well as actions. The URL pattern for routes in MVC applications typically is domain/{controller}/{action}/{id}.

When a request is received, it is routed to UrlRoutingModule-->MvcHandler. The MvcHandler HTTP handler determines which {controller} to invoke. The action value in the URL determines which {action} method to call, with which ID parameter if {id} is specified.

How to Choose Controllers

In general, the ASP.NET MVC control action blocks the ASP.NET thread pool while the action is being completed. This is called synchronous programming model. But in some scenarios it is desired that the action will not block a thread in the thread pool. For these scenario we can use async controllers that are being introduced in .NET Framework 4.5.

These are the benefits of using async controllers:

  1. For I/O, network-bound, or long-running and parallelizable requests, making async method will increase the responsiveness of the application
  2. It can be more easily canceled by the user than a synchronous request

Now you might think what the fresh hell is this? When to use sync controllers and when to use async controllers?

Fear not, you do not have to choose blindly whether to use asyn or sync. Scenarios that fit with synchronous actions:

  1. Simple and short-running operations
  2. Cases where simplicity is more important than efficiency
  3. CPU-intensive operations 
  4. When an action must perform several independent operations

Scenarios that fit with asynchronous actions:

  1. Long-running operations that are causing a bottleneck in performance
  2. Network- or I/O-intensive operations
  3. When the application requires the ability for users to cancel a long-running operation
  4. When IIS is required to service more requests by using asynchronous methods

Note to remember, if the controller action is CPU-bound, making the call asynchronous won't provide any benefit and might add an overhead for such operations. Since an asynchronous controller does not change the amount of time the request will take, it just frees up the thread executing the request so it can be allocated back into the ASP.NET thread pool.

How to Define Controllers

Physically a controller is just another class that must be post-fixed with the "Controller" word that can expose controller actions. When a user enters a URL into the browser, the MVC application uses routing rules to parse the URL and to determine the path of the controller. Any method that is defined as public is considered an action method. There are some additional requirements that must be satisfied by a controller action.

  1. A method used as a controller action cannot be overloaded.
  2. Controller action cannot be a static method.

How to Define Custom Routing

Any class derived from the ControllerBase class and having a name that ends with "Controller" does not require any custom routing declaration. But you can define your own route as well. A custom route constraint enables you to prevent a route from being matched unless some custom condition is matched. If you want to add custom routes in an MVC application, you use the MapRoute(RouteCollection, String, String) method in Global.ascx.

When you define a route, you can assign a default routing value for a parameter. The default is utilized if the value for that parameter is not present in the URL.

Testing Controllers

If we do not test our controller's behavior, the motivation of using MVC will not satisfied. ASP.NET MVC controllers are nothing but simple classes, and controller actions are nothing but simple methods. So this approach makes the test case writing a lot easier.

We can conduct two types of testing on the respective controller:

  1. whether or not the correct action result is returned from the controller action.
  2. whether or not the correct view is returned for a view result.

For example purposes, let's write a unit test for the home controller. Here is our very own default HomeController:

In order to test the HomeController controller actions, all we need to do is create a new instance using the default constructor and call the action as shown below. 

The above test demonstrated may not satisfy or cover every aspect of a unit test for a controller, but it's good to start with. Advanced readers can check the references given in the next section. I hope to cover a full post describing different test cases for controllers.

References and Good Reads

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here