Introduction

In this article, I will show how to use the Model View Presenter pattern to remove logic from the UI and move it to a Controller class. Furthermore, I will show an easy way to enable threading within the application and follow the rule of "no business work should be done in the UI thread". By applying threading correctly, you should never have a situation where the UI is blocked while processing some business work.

Logon Example

To show the MVP pattern and all its glory, I decided to use the logon screen example. We are all familiar with logon: a screen shows up asking for the user name and password. When the user presses the "Logon" button, work is initiated to validate if the user is authenticated on the system. Normally, logon is quick; however, in complex systems, logging-on can take a significant amount of time. I am going to show how to handle long operations with MVP, using a tiny framework which is based on the thread pool. But, first things first, let's define our screen.

Creating the View

Views are really our UI layer. Normally, these would be web pages or WinForms. In this example, I will use WinForms. Using MVP, the View should really expose no business logic whatsoever. In fact, if you need to add an if statement, you should ask yourself if it belongs in the View or the Controller; unless your if statement relates with UI work, it probably belongs in the Controller. The way I see Views in MVP, are as classes that, at the core, expose only properties and events - nothing else. There could be exceptions to this rule, but the goal is to make the View very simple. The View knows how to get data, and how to set data, but it doesn't know in which sequence or why. It is like a dummy puppet that provides all the ropes but without knowing the actual act.

Suppose our logon screen will have a user name field, password field, a status field (indicating if there is an error), and a button for performing the actual log-on. We can define the interface for the View without too much trouble.

Notice, the interface contains a property with a setter and getter for each field, and an event for pressing the log-on button. I have also added the Notify method, so I can notify my View from the outside. This method is used to setup the status field indicating if the logon is successful or not. I will talk about this method later. Using the ILogonView interface, we get the extra benefit of having a View implemented in different ways; it can be a web page, or it can be a WinForm. It can even be a regular class - just used for testing.

The Controller

The job of the Controller (or the presenter) is to handle the events coming from the View, and use the View getter and setter properties to define the behavior of the View. Think of the View as a data source; just like a data layer, you can query the View for information, and you set information to the View. The Controller is the only component that knows exactly how to manipulate the View, and how to call the setters and getters in the right sequence.

The Controller is listening to the logon event that the View fires. When a logon event handler is triggered, the Controller queries the user name and user password, and validates if the user name and password are correct. If there is an error message, the controller sets the status message on the View with a message. However, there are a few problems... First, I don't know if you noticed, when I first showed the code of the View, it did not contain a reference to the Controller. Therefore, I need to modify my Form to include a knowledge of the Controller.

So far, we are classic MVP. If you have understood everything to this point, you have just understood MVP. Anything above this point is just little things that bug me.

The Controller is doing all the work. Normally, the logon work should not be done directly by the Controller but delegated to a business layer class, ideally, a logon service.

What if the logon takes 10 minutes to process, we can not keep the view frozen.

What if we would like to send the status back to the View during a business operation outside of the Controller. How do we handle that?

To be honest with you, I still feel the View should be beyond stupid and not know anything. But, as you can see, the View knows about its Controller and how to create it.

Using a Service Layer

OK. One problem at a time. The first task would be to remove the logon processing from the Controller and move it to a Service layer. Let's create a LogonService class, which accepts a user name and a password, and validates if the user is valid. Now, we will use our Service layer from the Controller to perform the logon operation. Same idea, the Controller handles the logon event handler and delegates the work to the Service layer. The Service layer actually does the work of logging, and updates the status message on the screen with the outcome of the operation.

But, here again, we have some problems. What if our Service is a long running service, and maybe executes many steps to log a user? This example is simple, but let's face it, it is never that simple in production code. We normally have to go to the database to validate a user. I would like to provide the service in some way to report the status back to the View. After all, our Controller can do this, so should the Service... An idea would be to introduce an interface to allow the Service to report the status, something like an INotify.

publicinterface INotify
{
void Notify(string notification);
}

Now, this should look familiar, our View has this method... (take a look).

Notice that ILogonView inherits from INotify. Now, we need to pass this INotify to the Service, so let's modify our Service. Other than that little change, there is nothing new with our View. Let's look at the Controller using the LogonService class.

The Service is created as a local variable to the event handler. It might be better to create the Service once and keep it during the lifetime of the controller, but then we have the problem of who creates the Service? It could be passed to the Controller on the constructor, or created directly in the Controller, but then, it might not be re-used by other Controllers. The best approach is to pass the Service to the constructor, but I am not willing to have the view create it and pass it. I will deal with this issue soon.

The Service is passing the view as an INotify. There is really nothing wrong with that, but if you think about it, it allows the Service direct access to the UI. A better way would be to have the Service talk to the Controller via INotify. Then, we are respecting the role of the Controller... (so I am going to make this change by allowing the Controller to implement INotify).

The goal was to provide the Service a channel to communicate to the View, so now it is possible for a long running service to report status. But, what if we don't want to report anything, and would like to run the Service without a View and without a UI? Notice that you can't create the Service without INotify. So, here is another problem, which I will deal with later. At least, we can say the logic of the logon is now outside of the Controller, and our Service is a little more powerful with its capabilities.

A note about DDD (Domain Driven Design). Notice, my Service is not very domain driven; it is normally at the Service level that we should see classes such as User and Authentication. For example, Authentication.Authenticate(User user), but I am leaving the domain model out of this article, because already I have a lot of problems to solve, and DDD deserves an article on its own.

Let's do a bit of re-factoring. First step, let's create the Service as a member variable of the Controller class. Let's also have the ability to pass the Service to the constructor.

The Service can be passed to the Controller, it's more flexible. But I am not changing the View, so this constructor will not be used.

I created the Service as a member variable if it is not passed.

OK. Let's step back a little. Most of you might be happy with this implementation of MVP, and it is kind of by the book. But, I am still not happy with it. First of all, who is going to create the LogonService. It should really be set outside of the Controller, or supplied to the Controller (but I hate having the View create the Service). Same problem with the Controller being created by the View. The View should have no knowledge of how to create a Controller; it would be nice if the Controller can be supplied to the View. The solution is to have a factory pattern to create the Controller, Service, and even the View! The solution to all these problems can be addressed with Dependency Injection (DI).

The View depends on the Controller, and my Controller depends on a Service. I can create a Factory that will create my View, addressing all the dependencies, and what do you know, there is a framework out there just for that - Spring.Net.

Using Spring.NET for Dependency Injection

To tell you all the truth, I am new to Dependency Injection. However, it was not complicated to learn, and it solves the issues of object creation and dependencies. I chose to resolve all dependencies using setter properties. I have also created interfaces to all the classes that require dependency injection. The Controller interface:

The logon service interface now allows an INotify to be specified as a setter (so if I wanted, it could have been initialized using DI as well, but I am not doing it in this example).

I provide an empty constructor, so now, I don't need to have a notify object for creating or running the Service. However, in case the INotify is not passed to the constructor or not set by the setter, I provide an EmptyNotify, which is similar to having the mNofity set to null. However, because this empty class implements the interface, I don't need to check in my code if the INotify object is null, or if it is passed.

The nice thing about the new version of the View is that it is now simpler. The goal was always to keep the View unaware of the business work, and even something simple as creating the Controller is now outside of the View. Like anything in MVP, there is a property to set the Controller.

Setting Spring.Net

So far, I have tried to avoid talking about Spring.Net, but at this point, we are ready to deal with Dependency Injection. The first step is to get Spring.Net and install it. Don't worry, it is safe. I have done it many times, it will not break anything on your computer. You can download Spring.Net from here.

This example is using version 1.1 of Spring.Net.

The next step is adding a file reference to Spring.Core.dll into the .NET project.

Now that we have Spring.Net, all that is left is to specify the dependencies for creating the objects (View, Controller, and Service). To do this, I have used the app.config to specify the dependencies in XML. The XML is simple to understand. Jere is a copy of my App.Config for the Logon MVP example:

All the other dependencies are taken care of by using Spring.Net. At this point, our Logon application is initialized with the correct version of a View, Controller, and Service. Notice that this allows us to "switch" the implementation of a dependency, just by providing a new implementation of an interface and configuration change. For example, to provide another version of the LogonService that will contain additional work, we just need to tell Spring.Net which version to "inject". At this point, I wanted to finish my article, but I noticed that there is one more issue with this MVP pattern. The case of having a long running service, and the risk of freezing the UI while processing the Service. To solve this problem, I have introduced a simple yet powerful little threading framework.

The UI Should Never Freeze

The main problem with UI and threads, is that the UI is not allowed to be accessible from any other thread than the thread it was created in. This means that if our application starts to create threads, and performs processing in threads, it is not legal to have these threads update the UI (via an interface or not). In fact, trying to update the UI from another thread will cause a runtime exception in .NET 2.0, and unpredictable results in version 1.1.

So, our first goal is to make sure the UI is able to update correctly, no matter from which thread it is called on. To do this, I have added a base class to my LogonForm, called View. My base class contains only one method, UpdateUI; this method accepts a delegate of type MethodInvoker, and makes sure this delegate is executed on the UI thread.

Notice: for the getters, I needed to store the return value outside of my anonymous method. This is because my delegate does not accept a return value. This is an issue I plan to resolve in a second part of the article... (using AOP to handle UI threads safely). Now, we have to surround all our View public methods with this uiDelegate. To make the job simpler, I made a C# snippet that allows you to select the code within the property, and then apply the "view thread safe" snippet. Here is the snippet, if you want to use it:

Now, our View is able to update itself, no matter from which thread it is being called from. The next step is to actually use threads within the Controller. Suppose the logon takes 5 seconds to logon. To enable threading at the Controller level, I can use the same approach I used for the View. Using delegates... Notice the new base Controller class.

I don't really care for output values or return code, and this is mostly due to the MVP pattern. When I implement my Controller function, I can know when to set values to the View.

Notice that I still make sure EndInvoke is called. This is for two reasons: first, to make sure I get exceptions, and second, making sure there is no resource leak. Calling BeginInvoke without EndInvoke may cause resources to leak.

If there is an exception, I let the child Controller to take care of it.

I modified the logon service to simulate a long running operation, by sleeping for 5 seconds.

Just one note: now, when you execute the program, the UI will not freeze when pressing logon (the way it should be). However, that doesn't stop the user from keeping on pressing the logon button. It is important to add to the View additional functions to enable and disable the button. I didn't do it in this example; however, it works well with MVP, but provide a setter method to enable or disable the logon button.

Conclusion

We went a long way from our simple logon application. We have removed most of the logic from the View, keeping the View very simple. We have used DI to allow the application to inject the Controller and Service into our view. Finally, I have showed a way to enable threading without making major changes. The idea is to wrap UI functions with thread safe code, allowing all UI code to be marshaled to the UI thread. The only last re-factoring left to do is to remove the thread safety wrappers, and find a way to have them done with an Advice using Spring.Net. That way, we can keep the View simple, not even knowing about the threading work.

However, I think this will be done in my next article. I hope you enjoyed this article - Happy .NETting.

Share

About the Author

I am currently working as a team leader with a group of amazing .NET programmers. I love coding with .NET, and I love to apply design patterns into my work. Lately I had some free time, so I decided to write some articles, hoping I will spare someone frustration and anxiety.

Comments and Discussions

I've a situation where my windows form consist of a datagrid which get the list of files to parse and download. I've managed seperate the file download process into a class and after each file download the status is shown in datagrid through threading.
Please give me an idea on how to implement this using MVP pattern.