Story Details for articles
Golf Tracker - Ep. 6 - Presentation Layer and Unity
8/24/2011 7:50:08 PM
8/24/2011 7:50:08 PM
Golf Tracker - Presentation Layer and UnityIn this episode I explain many aspects to what I need to do to prepare the presentation layer to receive and process data from the service layer and other sources.
Dependency Injection with UnityThere are many Inversion of Control (IoC) containers to help you with dependency injection. In this application I've chose to use the Microsoft Practices framework called Unity. Others include:
- Microsoft.Practices.Unity - version 1.2
Here's what the project references look like.
Unity BootstrapperTo encapsulate the Unity functionality even further, and to make it easier and neater to refactor in the future, I've created a Bootstrapper class where all the mapping of concrete classes to interfaces will be handled. Here's a look at the Bootstrapper class.
(NOTE: this is the final implementation of the bootstrapper class with all the class mappings. The video only shows those classes that are completed at this point.)
To make this work nicely, I need to include my Unity library which is called on line 33. The UnityFactoryBuilder.Init(container) method creates the controller factory class that handles the resolving of the concrete classes to the interfaces.
Once this class is built, I simply reference it in the Global.asax class and I'm good to go. Here's how it is used.
Line 32 contains the call to the Bootstrapper class. That's all that's needed to configure Unity using my library helper. This helps make the Global.asax cleaner so it doesn't contain all the mappings.
Also, the Bootstrapper class can also be in it's own project for easier deployment, but some other refactoring to your application would need to be done, but it is an option.
Setup your applicationNow I want to finish setting up my application so I can quickly add functionality to it. In order to do that I've borrowed some ideas from the KiGG application. What these ideas help me do is implement a way of pulling common data that will be needed in either every controller call, or every view.
MVC is built on top of the concept of "convention over configuration". This means that specific conventions drive the framework, such as the name of a controller is also the name of the folder for the views it will display.
I also have incorporated various conventions in the way I build my MVC applications. One of them is the use of view models for 99% of all view presentations. In other words, I pass a ViewModel or ViewData class of some sort to the view and NOT simply the business object. This allows me to easily pass various pieces of data that may be needed for that view, such as data for dropdown boxes, or any other related information.
Following this thought, I've built my controllers to use custom ViewData classes for each business object that contains both a single business object, and a collection of business objects.
You'll notice that this ViewData class (as does all others) inherits from a BaseViewData class. This class can contain any common data that you want to pass up to the controller, and/or to the View. More about this in a moment.
Side Note: another convention I use, primarily since I use a code-generator to create much of my CRUD operations for my application, is the way I handle the property name for collections. In the example above the CourseViewData class has two methods for the Course business object, a single Course property and a List of Courses. For the collections (List<Course>) my convention is to append the word "List" to the name of the business object. This works out much better than just trying to append an "s", making it Courses. This tends to muck up generated code from the code-generator unless you have an extremely intelligent Pluralizer. Because while this will work for words like Course, it wouldn't work for words like News. What's the plural of News, Newses?? So by having the naming convention for pluralizing names, I append the work "List". (Another Note: this really only works if your naming convention for the business objects to begin with are singular.)
By creating a few different classes I'll be going from something like this in my controllers:
... to this ...
Notice that I'm now calling a ViewDataFactory static class instead of simply creating a new instance of the view data class. What this does, under the covers, is it pulls data from various sources, sets a base class with properties and sends them back up to the controller and eventually the view to be used as necessary.
The BaseViewData class is simply an abstract class that contains properties that will be populated by another class.
Here's a look at the folder structure for the ViewData folder.
It's the BaseViewDataBuilder class that will populate the BaseViewData classes properties.
In this example, the values that are setting the properties are coming from the appSettings config file, but they can easily come from a database.
By using this methodology to create my ViewData or view model for the View, I am passing essential data up the stack without any repetitive work. This also makes it easy to refactor what values I need to include by simply modifying the BaseViewData properties and then setting them in the BaseViewDataBuilder class.
ConfigurationAnother thing I do to setup my application is to extract out the appSettings and connectionStrings sections of the web.config. By doing this it enables me to have settings and connection strings for development and a different set of settings for production. So whenever I need to publish a new version of the application to the production server, I won't be overwriting any production settings with those for development.
Here's how I enable this in the web.config.
Here's a look at the files in the root of the project.
Then I can use a class to get the appSettings properties to use in the BaseViewData class.
Displaying the UIOnce all the action methods are created in the controller, it's easy to create the views. But as you would imagine I have a certain convention for my basic CRUD views.
When it's possible I like to have a UserControl (Partial View) used to contain the actual form that is used for both the Create and Edit views.
Here's the CourseFormControl partial view.
And here is how it's used in the Create view.
And the Edit view is nearly identical.
For me, this makes it easier to make common modifications to the form and have it reflected on both views. DRY!
Notice that in both cases, the RenderPartial HTML extension, passes in a Business Objects Course, instead of the entire CourseViewData class. This is what the partial view is expecting, while the primary view is expecting other information such as the PageTitle and SiteTitle.
ConclusionNow that the MVC application is setup (for the most part), the next thing I want to do is use some tooling that will help me generate controllers and views that are completely rendered exactly the way I need them for this application, instead of manually creating them every time.
In the next couple of episodes I'll demonstrate how to use and customize T4 templates to build custom controllers and views.