Recently, I wrote an article on the development of a master-page framework in ASP.NET. Master Page framework was an extension of the ASP.NET
UI.Page framework, and most of it is related to the static appearance of the Page. Then, I started receiving emails about the dynamic behavior of pages, and controlling the interactions between user-controls on a page, and communication between different pages etc. So, I thought there is a need of discussion on this aspect of the .NET Framework, and this would not be possible without mentioning the Model-View-Controller Design Pattern, that is embedded everywhere in the ASP.NET Framework. This article is composed of two parts. In the first part, we will discuss in detail about the Model-View-Controller Design pattern in context to ASP.NET, using UML, and finish our discussion with writing an example application as a bonus for its implementation. In the next part of the article, we’ll wrap up our discussion with dynamic aspects of pages by explaining different types of fine-grained controllers with their design and implementation, and we’ll discuss about the details of the HTTP pipeline too and what is the best approach to use it; so stay tuned, lot to come .
Model-View-Controller Design Pattern:
This is the classical and most famous of all design patterns especially when we talk about User Interfaces. A user interface is basically a presentation layer of some sort of model-data. If the data changes, the view is updated accordingly, or vice-versa. In this particular scenario, if you look closely, you can observe that there are two objects involved for performing this task, i.e., a View and a Model. There might be more than one view of a data model. Like, one view could be a Grid presentation, and other could be a Graphical Plot of some sort, like Bar chart or Pie chart, or so. Here is how it would look like:
I know, you should have these questions now, like how the view object would talk with the model object and vice versa, and how we want to look at the model, which part of the model will go to which view and which part of the view and how. Now, we are talking about one other object, the controller object; this controller object acts as glue between model and view. Controller object is basically a business object, provides the answer how we want to view the data, what rules should be applied for its presentation or so, and what will happen if some one changes some parameters in the view, how to react to some key-board or mouse events if this is an interactive application, and some times you need to update the model and send messages to other views that the data is changed, so that they can postback a request for updating their own contents. You will get all these answers shortly!
This Model-View-Controller can be best described visually, using robustness analysis, first introduced by Ivar Jacobson, in his award winning book on Object Oriented Software Engineering (see reference below), and was further explained by Doug Rosenberg et al in his book, Use Case Driven Object Modeling with UML. Robustness Analysis involves analyzing the narrative text of use cases, identifying a first-guess set of objects that will participate in those use cases, and classifying these objects based on the roles they play, and it helps you partition objects within a Model-View-Controller paradigm. Robustness analysis enables the ongoing discovery of objects, and helps you ensure that you've identified most of the major domain classes before starting any additional design or development. Ivar has classified them as:
- «entity» objects depict long lived objects, deals mostly with the persisted states.
- «boundary» objects depict links between the system and environment, communicating.
- «control» objects depict use-case-specific behavior.
Entity objects are no more than the information or data your boundary objects are looking for. These might be database tables, Excel files, or might be "transient" session or cached data or so.
Boundary objects are the objects with which the actors (for instance, the users) will be communicating in your software system. These might be any windows, screens, dialogs and menus, or other UIs in your system. You can easily identify them while analyzing your use cases.
Control objects (controllers) are the business objects or your business web-services. This is where you capture your business rules that are used to filter out the data to be presented to the user he has requested for or something. So, the controllers are actually controlling the businesses needs or the business itself.
Here are the visual icons of these three UML stereotypes:
Rules of the game:
Here are the four basic rules you should enforce when extracting these objects while analyzing your use cases and making interaction diagrams among these objects:
- Actors can only talk to the boundary objects.
- Boundary objects can only talk to controllers and actors.
- Entity objects can only talk to controllers.
- Controllers can talk to boundary objects and entity objects, and to other controllers, but not to actors.
If you look at the above figure, you can see the only access point for an actor to reach any object is through the Boundary objects. Boundary objects can’t talk with each other. While Control objects can talk freely with all of the objects except that it has no access to the actor or the user of the system. And the Entity objects can’t talk with each other too; they can access each other but through the Control object. Also, an Entity object can only reach Boundary object through the Control object. So the Control object is really a media of communication between each layer, and that’s why it is suited for business rules.
Robustness Analysis and Model-View-Controller:
Now, we have all the rules in place, let’s see how these objects are related to Model-View-Controller paradigm. Well, good news is this, that they have one-to-one mapping with the objects, derived from this analysis:
- Entity object maps to Model object,
- Boundary object maps to View object, and
- Controller is same in both.
And the other good news is that the same rules are applied to these objects too. It means, when we are doing Robustness Analysis, we can use Model-View-Controller objects in place of Entity-Boundary-Controller objects. Here is how our objects would look like now:
And here is the simplistic and hypothetical sequence diagram for MVC. What you see in this diagram, a web-user initiated a query and an event is generated that is handled by the controller and gets information that is needed from the model, validates the information and passes back the result set to the view.
Model-View-Controller is an approach for segregating different layers, in such a manner that it can be easy to maintain for a moderate to very complex application. It would be best suitable when you are making something for the web, where the business rules change frequently with time. Also, it’s the best way of writing applications in a service oriented architecture, where you write/encapsulate your business rules in a separate web-service than the Data-Access Layer, where the service is only dealing with Model/Data related stuff. Since the user interfaces are also separate, you can build powerful Custom Controls, and put them in the User-Controls for deploying as Pagelets. And finally, what is left, you need just to build proper interactions for them, enforcing rules mentioned above, while designing any solution.
So, let’s see where we stand now: we now know what these model-view-controller objects are, how they look like, and what are the rules we should enforce when we do analysis of a particular use case scenario and making interaction diagrams out of them. Let’s take an example scenario and explain it using this technique!
Use case (UC.1.001):
User shall be able to logon to the web-application.
Here is the UML diagram for this use case; it shows an actor (web-user) and logon use-case relationship, it would more be elaborated when we go into the analysis phase of it. I am taking a very simple case, of login and deferring the registration use-case for our example, for making it simple and understandable at the first go.
Before going into any analysis, it would be better, or I call it, it’s a must, that you should have the visual prototype in front of you. Here is how our prototype would look like:
What it means, that the user is presented with a logon screen, where he can enter his identity and press the Login button for access to the system. The user can also turn on the check-mark on the check box for remembering him; in that case, a cookie is needed on his system, to be enabled. Also, when he logs in, a new session is created on the server side for keeping his activities alive while using the web-application. With all these, let’s elaborate this scenario using the Robustness Analysis diagrams:
Let’s take a closer look at the above diagram. User interacts with Logon Screen (the view) that has one submit button for login (has-a relationship in UML is shown with a diamond shaped line at one end), and has a checkbox for enabling the cookie storage or so. What happens when the user clicks on any of these two buttons, the request goes to the
MainController object, which then decides what to do with these actions, since it has all the logic built for handling those events, and then does some validations from security control object that in turn takes data from the Data Access object?
MainController then creates a session for this user, it also stores user's info like encrypted passwords, in somewhere in the cookie store or so. With this analysis, we are now very much clear that, apart from the logon screen, there would be four other objects involved in this scenario;
SessionState object, the
CookieStore object and the Database Access objects. It does have given you an idea what are the objects required to do a particular job, but it does not tell you what functionality is needed for accomplishing this task. For that, we need a sequence diagram, here is how the sequence diagram should look like:
After careful study of the above sequence diagram, we can safely classify our objects as there should be a
MainController, that takes care the business logic for the page, and a
BusinessService object that takes care of all the validation, Session Management and cookie setup stuff. There would be a
DataAccessGateWay (model) object that encapsulates all the details of talking with the back end database. Here is how the class diagram looks like:
Isn’t it beautiful that all of this robustness analysis leads us to a design where we can define our first set of detailed class diagrams? I know you’ll love it.
The most important of all of the objects above, are the business objects that are the controller objects. Now, let’s have a closer look at how ASP.NET framework facilitates us in defining these Controller classes.
ASP.NET and Model-View-Controller (MVC)
Basic idea of MVC is to segregate the presentation layer from the business layer and the Data Access Layer, or the model. Let’s see how it is done in ASP.NET.
Let’s have a closer look at this picture,
Controller is bound to some model, and updates the
View when the data changes or vice-versa. So, the view depends on the model, passively. We achieve this goal, with the code-behind feature of ASP.NET, the page/user-controls logic is separate from that of the view, that is presented either in “*.aspx” files or in “*.ascx” files. And the controls you add to the page-controller, i.e.
System.UI.Page, you try to make them data-bounded as much as possible for consistency and synchronization. And also, you embed your event handler’s logic in the page controller using the code-behind feature. And if your architecture is service-oriented architecture, then you can introduce another controller as a business service (might be security service) that talks to the back-end model as needed and returns secured data to the Page Controller. Here is how it would look like:
It's Showtime (bonus++):
As a bonus, we would be developing a full fledged master-details web application that will give you enough details about model-view-controller (MVC) and its inner working, as well as a way of communication between different user-controls without even knowing each other. Also, with it you’ll get a reusable library that is composed of classes
MsSqlDataLinkAdapter. These objects are wrappers around ADO.NET Connection and Command objects.
Master-Details ASP.NET Application
The application is a web-application that has a master-page composed of a company logo, a banner, main contents, and footer. Main contents should display a parent-child relationship in the form of grid-view. There shall be two grids, the top one would be the master grid and the bottom would be the details one. When the user clicks on any item in the master view, the details/child view changes accordingly and should display the related child data.
Use-Case001: User shall be able to view/manipulate the master-details for Northwind Customer/Orders tables.
We would be applying the same technique as in my previous article, that is Pattern Oriented Architecture and Design (POAD). For this, we need the prototypic pattern of our system we are planning to design. And here is how the prototype would look like:
So, what we see is what we get, that is, our application would be composed of a
MasterPage, an HTML frame container, then HTML Table, and this table would contain further the two controls, Master-User-Control and the Details-User-Control. These user controls in turn would contain the
DetailsDataGrid Views. Here is the static inventory of the objects, needed to fulfill this job:
Robustness Analysis of the Use-Case001
We now have some understandings of the objects needed to fulfill this job, but before going into the detailed design, we need to analyze the use cases, to find-out the proper interactions and relationships among them. This would be done using the Robustness Analysis, while keeping into our mind the MVC concept. Let's draw the conceptual Robustness Diagram for this scenario:
What it means, that the user is presented with a master-details view. The upper Master-Grid-view is used to select the master table items. So, whenever the user selects master item, the child view is updated accordingly. Let's see how we achieve these interactions between objects. Look at the above diagram closely and you will see that when the user selects an item from the master-grid-view, the
MasterUserControl would be notified, and that in turn notifies this event to the listener, that is the
MainController object would notify about this event to the other listener, the
These user-controls have direct access to the Model (
DataAccessGateway) that uses
MsSqlDataLinkAdapter to establish MS-SQL database connections (for OLEDB connections, use the other adapter,
OleDataLinkAdapter). This is a classic example of the MVC and its inner working. Here is the object interaction diagram for this particular scenario:
MasterController and the
DetailsController are differential Controllers, that they are responsible of controlling one User-Control at a time and fine tune them while the
MainController object acts as an integrator, or a channel for these two controllers to pass information to and fro between them. Let's see how we are planned for them to work. For an object being a Notifying object, needs to implement the
INotifier interface, while a Listener object needs to implement the
IListner interface. Also, a listener object needs to attach itself with the relevant notifier in-order for being notified. In our case, we have the Master-Controller and, the Details-Controller is the listener.
MainController is both listener and notifier, and acts as glue between them.
Now, at this point, we have all the information about the objects, responsible for doing the job, how they would look like, and about their behavior and functionality. Let's now design them and develop the complete class design. And here is the detailed class diagram for this application:
Implementation using C# and ASP.NET
Code hierarchy is shown in the following figure, where you will find DataAccess adapters in Shams.Data.dll, updated MasterPage Framework library in Shams.Web.UI.MasterPages.dll, and I have collected some libraries from different sources on the web, you’ll find them under Shams.Web.UI.WebControls.dll. The sample application is in
Shams.MVC.WebApp namespace. All you need is to open Shams.MVC.WebApp solution and you are ready to go. And verify the virtual path in the file “Shams.MVC.WebApp.csproj.webinfo” to be created in the IIS. Here is the one for it:
<Web URLPath = "http://localhost/shams/MVC/WebApp/Shams.MVC.WebApp.csproj" />
Here are some code snippets, from the application, starting with the web.config. The
AppSettings section in the web.config file would contain two things for this application, the connection string for the NorthWind
DataTable, and the path to the
Here is how it does look like:
<add key="MasterPageUserControl" value="MasterPageUserControl.ascx"/>
The model is the
DataAccessGateway class and it returns the
DataSet that’s been used in the Master-Details data grid controls. Here is how it looks like:
It uses the
MsSqlDataLinkAdapter that is a wrapper around ADO.NET connection and command objects. This is a singleton class, with all of its functions being static. Here is the skeleton of this class:
In our particular scenario,
DataAccessGateway uses this class, to connect to the MS-SQL NorthWind database, by calling the
Connect(.) function of it. Once you have this connection object, you call another function
FilldataSet(.) to return you a brand-new dataset being used for data-binding. Once it is done, you call
Disconnect(.) to close the connection object.
Other notable classes are the controller classes,
UcMasterDetails (Main-Controller) and two other classes,
UcMainContentsMaster (Master Controller) and
UcMainContentsDetails (Details Controller). Here is how we connected these two classes with each other using
UcMasterDetails as a mediator.
And finally! Here is how the application would look like when you run it.
The MVC pattern I used in the application is the minimal use of it, but it’s the best pattern being used in all the navigations between pages and between controls. It also depends on how you plot a plan for your application in making a prototype application. So folks, that’s it for now, I have tried to un-cover everything about the MVC design pattern, with some useful applications for its implementation. This is one of the most commonly used and misunderstood pattern. I tried to make it simple and give you all the details it carries, along with the robustness analysis, that’s the key in analyzing such applications.
There is always a point of improvement in any system, and the same here is applicable too. I haven’t talked about any efficiency related stuff, because that itself needs a full article. So, I am putting this responsibility on you to go through the documentation for improving efficiency of ASP.NET applications, like Caching, View-State Management and Session Management, and How to avoid round-trips to the server, like post-backs etc. And I would appreciate if you involve me in your findings, thank you very much.
Q) What do you consider when architecting and implementing a new system being successful?
A) Your vision should be broad when you architect or design it, and should be focused while implementing it.
They were my answers, but you are welcome to send me your answers at email@example.com, and I will post them on my web site very soon.
- Object Oriented Software Engineering by Ivar Jacobson.
- Design Patterns by Erich Gamma, et al.
- Patterns Of Enterprise Architecture by Martin Fowler.
- Use Case Driven Object Modeling with UML by Rosenberg et al.
- UML Case Tool: Enterprise Architect from www.sparxsystems.com.