In my last tutorial, we covered how to get data from Umbraco and display it in Umbraco. If you are new to Umbraco and you haven't yet read the Umbraco Helper? then I would head there first. In today's guide, I am going to explain how to create your own MVC controllers and intercept the Umbraco routing. After we intercept the Umbraco pipeline, we will then return a custom View Model back to the templates.
Why Use A Controller?
When you work with Umbraco, because of it's flexibility, you can create a lot of the document types and templates directly in Umbraco. When your site gets a bit more complex and you need to do things like talk to a business layer to get additional data for a page, unit tests your code, remove logic out of your templates or a host of other things.
In How To Create A Document Type In Umbraco and create a page with it I explained about document types.
On most projects, you will usually create one controller for each document type. To get started, first open Umbraco and find the document types 'Alias'. NOTE: If you use the name the controller will not get hit:
Next, create a new controller. When you create a new MVC project the installation wizard should have created a 'Controllers' folder. Depending on how you want to structure your code, you can create your new controller in here, or somewhere else.
I personally like to keep all my C# code in a separate project but for simplicity, I'm assuming you will create you use the default one. If you are adding MVC to an existing project then you will have to create it yourself. In case you're wondering what a controller is... a normal MVC controller is just a C# code file, that inherits from 'Controller' and has controller prefixed in it' name, so for example MyPageController.
The only real difference with an MVC controller is that it inherits from an Umbraco base controller, rather than a Microsoft one. If you are new to MVC then this rule of having the controller in the name, is a Microsoft thing rather than an Umbraco one, so in this example, my alias controller will be called umbHomePage, so my class would be called 'umbHomePageController'.
After you have created the controller, the next step is to change the type the controller inherits from. In a standard MVC controller, we inherit from 'PageController', in Umbraco we inherit from 'RenderMvcController'.
If you run your code and try to load your page the 'Index' action should be run.
What If I Have Multiple Templates Associated To a Document Type?
You may not have thought about this yet, but what happens if you have several different templates associated to your document type? You may want different data returned depending on which template the content editor selected, or, you may even want a completely different view displayed all together. Luckily, Umbraco has thought about this.
For each 'template' that is associated to your 'document type' you can create a custom action that will be called. So, for example, if you had a template called 'HomePage', with an alias 'umbHomePage' set as the template for your 'document type':
You could create an action method called 'umbHomePage'. This action method would then be called in preference over the index action method whenever the document type is called with that template associated. The code will look like this:
When you load your page, umbHomePage will be hit first. If the MVC pipeline can't find a matching action method that matches the templates name, then the default 'Index' action will be called. This feature is pretty nifty as it gives the developer a lot of control over the mark-up.
Creating a View Model
Now we have a controller set-up, the next stage is to return a custom view model. When you normally create a view model you will still want all the pages data to be included in it, as well as any custom properties or methods. The code for the view model is shown below:
First, you can name your custom view model anything you want, but, in general, the view model should mimic the name of the controller you are using. The entity should inherit from RenderModel. The next step is to create a constructor, that accepts the CurrentPage, so we can use this data in the template. Without doing this, the only properties that you will have access to in the template will be the ones you define in the view model yourself. Next, in this example I'm returning the current time. After you have defined your view model, the next step is changing your controller to return the view model.
The code above is pretty self-explanatory. We pass the model we get in the constructor into the view model and then pass it back to our template using CreateTemplate().
Inheriting For The View Model In The Template
The last bit of the puzzle is to make the view model available in the template. In the previous example, the view inherited from UmbracoTemplatePage.
Instead, we want to tell the template to inherit from the model. We do this by inheriting from UmbracoViewPage and we pass in our new model as the type.
In today's guide, we've gone over how to hook into the Umbraco pipeline and get a custom controller to intercept any requests for a specific document type. We've created a custom view model and added some custom business logic and then returned it back to our view. If you are familiar with MVC or other CMS platforms this process should look pretty familiar.