Thursday, May 19, 2011

ASP.NET MVC Controller Out of Control

MVC pattern and Microsoft ASP.NET MVC implementation are quite popular and successful in recent years for many reasons such as modularity, readability, maintainability, and separation of concerns. However, out-of-box ASP.NET MVC may not fit well in some scenarios. You won't get the goodness of MVC without proper implementation. Recently when I reviewed one of our ASP.NET MVC applications I just found another example of how a pattern could become anti-pattern.

The ASP.NET MVC application is an internal authoring system letting people to manage a bunch of products and their attributes. The products then can be published and exported to a list of XML files that are used by front-end servers to display to public. This application's base domain model was quite simply: a Product has many properties and a Product belongs to one or more Category. The complexity goes to product properties and business logic behind them. That resulted in a huge Product controller in the implementation. The controller class is so big that the developer split it to a couple of partial classes to avoid thousands lines of code in one class file. That doesn't smell good at all.

The Product management UI has a few tabs which group different properties in a logical way. AJAX has been extensively used to populate and update those partial Product properties. Each UI component (partial view) has at least two corresponding controller actions, one for read and one for date. The controller was too complex and was doing too much: input and validation, data manipulation (CRUD), view mapping etc. It looks like going back to the old WebForm model and the controller is just like the code-behind we used to do in traditional ASP.NET.

This sounds like a common problem. Google "ASP.NET MVC big fat controller" there're thousands of results. Many people have been struggling on similar pain. Also many people provided suggestions or solutions to resolve the problem. I found one article with great insight on this topic that posted long time ago right after ASP.NET MVC 1.0 was released.

A handful esteemed people even built a new MVC framework on top of ASP.NET from scratch called FubuMVC when they found ASP.NET MVC had the problem along with other issues. If you want to stick with ASP.NET MVC, there're some good thoughts to slim the controller and make the applicaton more readable, extendable and maintainable:

1. ControllerLess action by one controller one action.
2. Grouping controllers.
3. Use AutoMapper to simplify the property mapping between different models.
4. Move logic and code to service layer as much as possible.
5. Use Command pattern to distribute responsibilities.

The last one Command pattern can be extended to Command Query Responsibility Segregation (CQRS) pattern, referring to this channel-9 video about applying CQRS to ASP.NET MVC 3.

Above ideas can be used together when we are doing ASP.NET MVC application developing or refactoring. It sure takes more effort at the beginning but it would pay off in the long run.