Controlling Controllers in ASP.NET MVC
Peter Vogel begins his series on introducing ASP.NET developers to ASP.NET MVC by looking at the C in MVC: Controllers
An ASP.NET MVC application consists of three components, obviously: Models, Views and Controllers. The Models are the middle-tier business objects that you might use with any application -- I'll come back to them later. The Controllers, on the other hand, are peculiar to the ASP.NET MVC environment and are critical to understanding the structure (and, therefore, the benefits) of building an ASP.NET MVC application.
Instead of requesting a page, the browser now really calls a Controller. You need to decide, early in the request cycle, which method on which controller a request from the Web browser should call -- a process called routing. I've discussed routing before in .NET 4. Fundamentally, you build a table with code in the Global.asax file that ties a method on a controller to a particular URL. While this is additional work not required by a traditional ASP.NET application, as I discussed in that earlier column, the flexibility and reduction in maintenance costs that result in using routing more than offset the work involved.
Controller methods are tremendously flexible. From a controller method (called an Action, a term that I'll use from here on because it's short) you return an ActionResult. An ActionResult can be a redirect to another page, a JSON object (useful for returning results to AJAX-enabled pages), or a View result, which results in a page. From your code in the Action you can also access any parameter data that was embedded in the URL that caused your Action to be called.
So, for instance, if the URL sent from the browser (or whatever client issues the request) is http://myserver.com/Customer/A123/Order/History/2009, then you might call an Action that displays the customer's order history. Within the controller you'd be able to access the data embedded in the URL: The customer number (A123) and the year to display (2009). Retrieving the data would be a matter of calling the right methods on the right business objects (the M for Model in MVC).
To create an ASP.NET MVC application, I used the ASP.NET MVC 2 template in Visual Studio 2010 (for earlier versions of Visual Studio, you'll need to download and install the ASP.NET MVC package) and selected the testing tool I wanted to use. I set up a routing table in my Global.asax file (again, see the earlier article) and then added a new Controller to the application (controllers are kept in the Controllers folder that is part of the project's template). Since this controller was going to handle all activities around customer history, I called it CustomerHistoryController.
An aside here: The flexibility of the controller methods means that it's worth investigating a Service Oriented Architecture design process. Because a controller can return such a wide variety of results, it really acts like a service: A Web page is just one output from this service. For SOA design, I follow a lite version of Michael Bell's Service Oriented Modeling Framework. Using that process led me to creating a CustomerHistoryController with an operation (Action) that returns a Web page for this particular request.
Back to the code: Within my controller I created a Controller called PurchasingByYear that expects to be passed a CustomerId and a Year:
Public Class CustomerHistoryController
Public Function PurchasingByYear(ByVal CustomerNum As String,
ByVal Year As Date) As ActionResult
'..code to retrieve purchasing data
An Action returns a View of the same name, so my next step was to add a View called PurchasingByYear to the Views folder. That means I have to discuss what a View is, which I'll do in my next column.
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.