PART III: Sitecore & MVC: Dependency Injection using Castle Windsor

In the previous post we made some changes to make the use of areas a little easier. In this post we be working on controller constructor dependency injection using Castle Windsor. The problem using this type of dependency injection is that Sitecore uses its own CreateControllerInstance method to instantiate the controller class. This method does not take any constructor parameters into account. In fact is just creates the controller instance passing and new object[0] as parameter. There is a way to avoid Sitecore’s CreateControllerInstance method: Just make sure this method does not receive a fully qualified type name and its assembly as value.

Let’s start writing some basic code to make sure we can even use Castle Windsor.

WindsorControllerFactory.cs

ControllerInstaller.cs

IntializeWindsorControllerFactory.cs

Now we have created a our own (Windsor)ControllerFactory which should take care of creating the controllers, a controller installer class to register the controllers to the dependency injection container and we made a Sitecore initialize pipeline processor to our ControllerFactory as inner factory of the SitecoreFactoryController.

Now add an interface and a class which implements the interface.

IDemoClass.cs

DemoClass.cs

DemoInstaller.cs

Now make some modifications to the code we already wrote in the previouse post.

DemoController.cs (non Area)

SitecoreMVC.config

Now publish and check out the result. Damn we got an error message. As i mentioned earlier the CreateControllerInstance method of Sitecore does not pass parameters. A solution can be changing the controller rendering item value of field “Controller” to “Demo”, but since we are using areas it is not an option because give us the multiple type error as described in the previous post. We can solve this with some new modification to the code we already wrote.

ControllerInfo.cs

AreaControllerRunner.cs

Demo1AreaRegistration.cs

The namespace of the controllers has to be present in the area route mapping

 

 

PART II: Sitecore & MVC: Areas

The basic MVC functionality works pretty well in Sitecore, but there are some MVC features that do not work as expected. One of them is the use of areas. Lets do some coding  examples and find out yourself:

  1. In our project we create a new controller named “Demo”
  2. Create a new view for your Demo controller named “Index”
  3. In the new view we write some HTML: <h1>Controller: Demo – Action: Index</h1>
  4. In Sitecore create a new Controller Rendering named “DemoIndex”.
  5. Set the value of field “Controller” to “Demo”
  6. Set the value of field “Controller action” to “Index”
  7. Assign our Controller Rendering to a placeholder on a page

In this example the controller will behave as expected. Now lets add another controller, but this time we do this inside an area.

  1. In our project we create a new area named “Demo1”
  2. Inside the area we create a controller and view using the same names we did in the previous example.
  3. Add the area name to the HTML of the view so we can see the differences.
  4. In Sitecore create a new Rendering folder named “Demo1” and create a new Controller Rendering as we did in the first example.
  5. Assign our Controller Rendering to a placeholder on a page

Our application throws an exception: Multiple types where found that match the controller ‘Demo’. The reason why this exception occurs is MVC does not known anything about the area and does not know which controller it has to use. Sitecore’s solution is to provide the fully qualified type name and assembly as value in the field “Controller” of your “Controller rendering”. Lets change both Controller Renderings, set the “Controller” fields to [Controller namespace].DemoController, [Assembly name]. And refresh our page again. Yeah we got it working again…………….., but wait i was sure our views had different HTML content. Why is this page displaying the same view twice?
The problem lies in the fact that the name of the area is not specified and thus the view can not be found inside the area. A solution could be specifying the path to the view hard coded in the controller, but in my opinion it is a terrible solution. The real solution to this problem is let to MVC know in which area the controller is executing.

Expanding the Sitecore Controller Rendering Item

  1. Create a new template named “_ControllerRenderingArea”
  2. Add a section named “Data”
  3. Add a field named “Area” of type Single-Line text and make this field Shared
  4. Add our new created template to the Controller Rendering template (/sitecore/templates/System/Layout/Renderings/Controller rendering)

Now we have expanded the Sitecore Controller Rendering Item it is time to write some to make it actually work.

ControllerInfo.cs

AreaControllerRunner.cs

AreaControllerRenderer.cs

GetAreaControllerRendering.cs

SitecoreMVC.config

 

 

PART I: Sitecore & MVC: Project setup

The last couple of months i have been busy researching and developing with Sitecore and MVC. During development I had some challenges to get it to work properly. In a series of posts I will explain some solutions for the challenges you will face after taking certain decisions.

Let’s begin with setting up a new Solution for our Sitecore MVC project.

Setup our Sitecore MVC Visual Studio solution

First we take the following steps to setup out new project:

  1. Install a new Sitecore instance
  2. Create a new Solution/Project in Visual Studio
  3. Select ASP.NET Web Application as your project type
  4. Select the “Empty” template
  5. Check the “MVC” checkbox under the section “Add folders and core references for”
  6. Click OK

In the next few steps we copy some necessary files to your projects:

  1. On the same level as your solution file (.sln) create a new folder external.
  2. Select the files: Sitecore.Kernel.dll and Sitecore.Mvc.dll from the Sitecore instance to your new folder.
  3. Copy the Web.config from the Sitecore Instance and we paste it into our own project (just overwrite the existing).

Almost ready. Create a publishing profile a make our publish target location is the root of the Sitecore instance and “Delete all existing files prior to publish” is NOT checked. Let’s click the “Publish” button and check if your Sitecore instance is still working properly.

We may get some errors about non matching assembly versions related to MVC and Illegal routing, let’s fix them. Since we create our project with an empty MVC project we have already installed MVC, but the references in the web.config – we copied from the Sitecore instance – probably do not match. By re-installing the MVC Nuget package the web.config gets updated with the proper assembly versions.

  1. Open the Nuget “Package Manager Console”
  2. Type: Update-Package -reinstall

Now remove all code from the RegisterRoute method in file App_Start/RouteConfig.cs, publish the project and check your Sitecore instance again, it should be working now.