The other day I was working on some features for MVC Turbine when I got a random idea about how we can use a new feature that comes with the Razor view engine (VE). This blog post hopefully will help out some of you in your development or least get your creative juices going.
@View with Razor Views
One of the new features that ships with the Razor VE is the ability to set ViewDataDictionary values through the use of a DynamicObject property. The following code shows how to do this:
The ViewModel.Message call is the equivalent of ViewData[“Message”], all which is done via the magic of DynamicObject. Internally, the controller uses an instance of the internal type DynamicViewDataDictionary in order to handle the get/set for values. This same instance is used to set the value of the View property for the WebViewPage type, the base type for all Razor-based views. Taking this simple approach we will implement something that will allows our views to tap into common services without dealing with the specifics of service resolution.
@Service Extension Point
Let’s first start by looking at the DynamicObject property that will wire things up for us. What we need here is a way to link a property name to an object instance that will satisfy the method call:
We need to translate the @Service.MessageService.GetWelcomeMessage() piece into a method call. We do this by taking the convention of @Service.ServiceContract.Method() and providing a way to enforce it. We do this via the DynamicLocator class:
As you can see, the DynamicLocator is a type that inherits DynamicObject and uses StructureMap to do the heavy lifting of service resolution. Since we’re treating every property as the service contract, we need to override the TryGetMember method to get the instance of the type that implements said contract. If the name doesn’t match a registered type, we need to throw an exception to inform the invalid service type. From here what we need to do is wire this type into the view, more specifically we need to wire this to the Service property of the view. We can do this by providing our own base view class:
This DynamicPage type exposes a Service which, as you can see, is a dynamic object; a DynamicLocator type to be more specific. Now, we all need to do is tell the Razor view engine to use this as the base type for the views it generates. We do this by modifying the Web.config within the Views folder:
Now we run things and see the following output:
I hope this blog post can help some of you out, or at least get your creative juices flowing. As you can see, it’s pretty simple to build your own conventions and flow once you get to grok the pieces that make up the framework. As always, check out the source and feel free to leave any comments!