Update: After seeing a post on StackOverflow.com I have updated my sample code to work with the latest MvcContrib available through NuGet that supports MVC 2.
This is part two in a multi part series, the first entry is MVCContrib - Portable Areas - Part 1 - The Basics. In that post we discussed how to setup and write a web site using a portable area (PA) that ran a Bing search. In this entry we will discuss how to send messages between the PA and the consuming application.
Our application will be a ‘search’ application that has two different search engines (Engine One and Engine Two). The PA will present the search forms and the search results. The search strings will be sent to the consuming application to run the searches. After the search is performed the results will be sent back to the PA to be displayed.
The MVCContrib library which can be downloaded from MVCContrib download at CodePlex. You will also need MVC 2 installed to be able to run the sample application. I have built the example application using Visual Studio 2010. I am planning on creating VS 2008 versions as well.
Lets Get Started!
The first thing we need to do is create the two projects, an MVC2 project for the consuming application, I named mine ConsumingApp, The second project is a class library project for the PA, which I called ViewsPA. Below are the required references:
- And a reference to ViewsPA project
Since we talked about the layout of the code for the PAs in Part 1 - The Basics I won’t go into that here. I will talk about the parts of the project that pertain to messaging.
The communication between the PA and consuming application is done via a synchronous message bus provided by the MVCContrib library. Messages that are put on the bus by the PA must implement the MvcContrib.PortableAreas.ICommandMessage<T> interface where T is implements the ICommandResult interface. The ICommandResult class is used by the consuming app to return the results to the PA. Enough of this…here is the PA’s side of the messaging in C#.
In the SearchResult class the Success property is from the ICommandResult interface. The remaining properties are there to illustrate the fact that you can have any number of properties and types of properties in the ICommandResult classes.
The SearchMessage class is what is sent to the consuming application. It implements the ICommandMessage<T> interface where the SearchResult class takes the place of T. When you implement the interface the Result property must be the same type as T. The Input property is a Query class which is a POCO and sends the search string to the consuming application.
The last bit of code I want to show is the controller’s action method. Since both SearchOne and SearchTwo are doing the same thing but just setting which ‘search engine’ to use I have created a base controller class to make life easier. The base class is here to process the user’s form submission and passes the query string to the consuming application.
The first line is a normal POST handling method. However once the model has been validated the controller starts the messaging process.
The first step is to create and load a SearchMessage object that will be sent consuming application.
Next the object is put on the bus and sent to the consuming application.
When the message is returned from the consuming application the method checks for success or failure of the processing. If it fails do something to inform the user otherwise display the results of the ‘search’.
That is all we need to do on the PA side. We added a few classes and lines of code to enable our PA to communicate with the consuming application.
In our consuming application we need to create a class to handle the incoming messages from the PA and wire up global.asax to register our message handler with the messaging bus.
First we’ll take a look at what code we need to add to the global.asax file. We need to add one line to the Application_Start method to receive the message being sent from the PA. We added a line that calls the Bus.AddMessageHandler method to notify the bus that we have a message handler of type SearchHandler. That class will handle all of our SearchMessage based messages from the PA.
The SearchHandler class inherits from the MessageHandler<T> class where T is the message that this handler will ‘handle’. Our class will override the Handle method from MessageHandler. This method is where we will do what we need to fulfill the PAs message. Hopefully looking at the code will make it a little more understandable.
The Handle method has a single parameter of type T. In our make believe search engine case our method checks to see what engine the PA requested. Instead of doing an actual search I am putting a canned message in the result object’s Message property that indicates which engine handled the request. The Message and Results properties are used in the PA’s results view. After this method finishes the PA’s controller method will pick up the results and call the appropriate view.
That is all there is to setting up messaging between the PA and the consuming app.
Lets Try It!
The home page is just about the same as it was in part 1 except that there are two tabs from the PA, Search One and Search Two.
Clicking on the Search One tab will take us to our new search form. We have a second field here to distinguish between ‘search engines’. When I submit my search string the PA sends the request to the consuming application which does the search and returns the results to the PA. The results will display the name of the engine used and the results also indicate which engine returned the results.
Adding messaging to our search application only requires slight modification to our consuming application. First we created a MessageHandler<T> based class that will respond to the PA’s message. Next we added a line to the global.asax’s Application_Start method to register you handler class with the message bus.
There was a little more work required on the PA side. We had to alter the action method to send the message to the consuming application. Once the consuming app is done the PA checks the results sent back the remaining portion of the action method is normal controller actions.
Why Would You Do This?!
Some of you may be wondering why you would do something like this with just the views on the PA. Where I work we may be using this approach to create an application framework with pluggable modules for different sites. The middle and data layers will be the same across all sites but certain locations will only use a few of the views. This approach will help us create multiple sites without having to create a complete web site for each location.
Part 3 of the series will either be on adding MEF to the picture or how to access a web.config file in the PA project.