To increase code reuse possibilities in your ASP.NET applications, you can use a couple of different patterns. Learn more about the Page Controller and Front Controller patterns and how you can implement them in your apps.
When developing complex dynamic ASP.NET applications, it’s important to minimize code duplication to increase the reusability and flexibility of the application. In some applications, users may perform many different actions that have different controller logic but result in the same view (e.g., showing a products list and allowing a user to add or delete a product will lead to displaying the same products view with the modified data after the controller leads the user through the add or delete process).
The first step toward developing reusable logic is minimizing the amount of code in scripted server pages. The logic on scripted pages is difficult or impossible to reuse and results in poor separation between the view and the controller. They are also more difficult to test and debug. Instead of adding script code to an .aspx page, it’s more efficient to implement the controller using classes, which allows you to implement common appearance and navigation across your Web application and reuse presentation logic throughout the application.
There are two different patterns that address the implementation of controller classes for ASP.NET applications. The Page Controller assists you in building an application in which the navigation patterns are static but the pages are generated dynamically. For more complex applications where the navigation is dynamic or configurable based on a set of rules (e.g., user privileges or application state), the Front Controller allows for a more efficient implementation.
Let’s look at both these patterns in more detail.
1. The Page Controller pattern
When using the Page Controller pattern, a central class called the BaseController implements all common behaviors required to handle the HTTP request, update the model, and then forward a request to the appropriate view. The BaseController handles common functions such as session management, security, and the retrieval of data from query strings or hidden fields. For each link in the Web application, you then create an individual PageController class that inherits from the BaseController. These individual PageControllers implement any page-specific behavior while using the core functions as implemented by the BaseController.
In many cases, your application can be decomposed into a series of common page types that share common logic. For example, you may have a series of data entry pages or grid view pages that all share logic. In such cases it may make sense to implement a DataEntryController or a GridViewController that inherits from the BaseController class. From these you can then implement PageControllers that use their common methods. You must be careful not to implement too many layers of inheritance or the application design may become difficult to maintain. You can minimize the inheritance chain by creating sets of “helper classes” with common code that any level of the chain may call.
To implement the Page Controller pattern, you create the BaseController class by inheriting from System.Web.UI.Page and then implementing the common application functionality. For example, the BaseController may implement a common look and feel by providing a header, footer, and some user-specific information (e.g., logon name and department). Then you create each page of the application by inheriting from this BaseController class and implementing its page-specific logic in classes placed in the codebehind file. This works for moderately complex applications with a fixed navigation path. If you need dynamic navigation, you need to implement the Front Controller pattern.
2. The Front Controller pattern
The Page Controller pattern becomes inefficient when you need to coordinate processing across multiple Web pages because of its implementation of a single object per logical page. The Front Controller is more efficient in such cases because it funnels all requests through a single controller and then directs requests through a single handler and a hierarchy of command classes. The handler retrieves parameters from the HTTP request, chooses the correct command, and transfers processing to it. After each command object performs the specified action, it can choose which view is required to render the page properly. Implementing the Front Controller results in more centralized application control because all page requests come through a single controller instead of being handled by different Page Controllers. But this can also be a liability if the handler does expensive processing, such as database lookups that could cause the entire application to operate slowly. The handler should be as efficient as possible and use external resources only when absolutely necessary. You should also consider caching any external resources to increase the handler’s performance.
You implement the FrontController class by creating a Handler and a CommandFactory, which determines the necessary command to execute in response to a request. ASP.NET provides the IHttpHandler interface to allow developers to create custom interfaces required to service incoming HTTP requests. You implement the Handler by inheriting from System.Web.IHttpHandler and adding the logic to instantiate and call the appropriate command from the CommandFactory. The CommandFactory defines a collection of commands and the logic that determines which of the commands should be executed. Calling the CommandFactory returns the appropriate Command object for which the Handler can call an Execute method. Using this pattern, you can create more robust navigation scenarios and implement them centrally by extending the CommandFactory logic and creating additional commands to handle the required scenarios.
Architectural patterns considerations
.NET Architects should strive to use architectural patterns whenever possible. Patterns such as the Page Controller and Front Controller are easy to implement using built-in features of ASP.NET, and they result in highly reusable and extensible application designs and implementations.
For more information and ASP.NET implementation details for these and other architectural patterns, visit the Microsoft .NET Architecture Center.