Archive

Archive for the ‘MVC’ Category

Sitecore MVC new Ninject Controller Factory – clean version

23/10/2012 2 comments

In this post we will have  revisit my last blog post, using Ninject with Sitecore MVC. In this new approach we will simplify the code to do the exactly same thing as in the last post LINK.
So what we want is to be able to inject Concrete implementation in the our Sitecore Controller.
We will do this by creating a ninjectc controller factory and forwarding  to the default Sitecore controller factory, so our implementation is used when Sitecore creates it’s controller. By doing it this way all standard Sitecore MVC functionality will still work, but we now have the possibility to inject our concrete implementation on creation time of the controllers.

First we need a Factory for creating the Ninject kernel


 public class NinjectKernelFactory
 {
   public IKernel Create()
   {
    return LoadAssembliesIntoKernel(new StandardKernel());
   }

   private IKernel LoadAssembliesIntoKernel(IKernel kernel)
   {
     foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
     {
      try
      {
        kernel.Load(assembly);
      }
      catch (Exception)
      {
         //Empty Catch used because ninject have problem
         //with loading some of the Sitecore MVC assemblies.
        // Method .ToString()
      }
    }
     return kernel;
   }
 }

With that in place we can create the the NinjectControllerFactory


 public class NinjectControllerFactory : DefaultControllerFactory
 {

  private IKernel _kernel;
  public NinjectControllerFactory(IKernel kernel)
  {
    _kernel = kernel;
  }

  public override void ReleaseController(IController controller)
  {
    _kernel.Release(controller);
  }

  protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
  {
    return (IController)_kernel.Get(controllerType);
  }
 }

]

All that is left is now for binding it all together in a new InitilizeContollerFactory


 public class InitializeNinjectControllerFactory
 {
   public virtual void Process(PipelineArgs args)
   {
    SetControllerFactory(args);
   }

  protected virtual void SetControllerFactory(PipelineArgs args)
  {
    NinjectKernelFactory kernelFactory = new NinjectKernelFactory();
    NinjectControllerFactory ninjectControllerFactory = new NinjectControllerFactory(kernelFactory.Create());
    SitecoreControllerFactory sitecoreControllerFactory = new SitecoreControllerFactory(ninjectControllerFactory);
    ControllerBuilder.Current.SetControllerFactory(sitecoreControllerFactory);
  }
 }

And off course we need to swap the originale InitlizeControllerFactory with our new one.

Sitecore default :

</pre>
<processor type="Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc"/>

Replaced with this:


<processor type="SitecoreNinjectModule.InitializeNinjectControllerFactory, SitecoreNinjectModule"/>

Now Lets try it our I have created a really simple example first an Item with a controller rendering on.

And the sourcode for the controller


public class StoryController : SitecoreController

{
 private ITestInterface _testInterface;
 public StoryController(ITestInterface testInterface)
 {
 _testInterface = testInterface;
 }

public ActionResult From()
 {

ViewBag.Froms = _testInterface.Get();
 return View();
 }
 }

And now to the View Code

And our RazerView


@model dynamic
 <h2>From vIew</h2>

@ViewBag.Froms

And a simple TestInterface and TestClass


public interface ITestInterface
 {
 string Get();
 }


public class TestClass : ITestInterface
 {
 public string Get()
 {
 return "Hallo From Test";
 }
 }

And the output of it all

There we are a much nicer and cleaner solution presented then I came up with in my last blog post and without breaking any Sitecore functionalit, and off course you can still unit test the controller.

Advertisements

Unit testing our MVC Controller for Sitecore

10/07/2012 Leave a comment

Is this post and as promised, we will unit test the controller we created in the last post.
So we will rewrite the controller a tiny little bit, so we can inject a child item repository, ie. creating a stub for the repository. Since Sitecore as default doesn’t ship with ControllerFactory where it is possible use dependency inject we will rewrite the controller instead, so it has a default repository it uses when Sitecore is instantiating the controller, and one it uses when testing, or more precisely you can pass one in to Repository property. The updated controller code is listed below. In my next post we will extend Sitecore so we can inject class through the contructor with dependency Inject using Ninject.

public class ItemController : Controller
{
private IChildItemRepository _childItemRepository;

public JsonResult Index(string id)
{
return Json(CreateObject(ChildItemRepository.Get(id)), JsonRequestBehavior.AllowGet);
}
public IChildItemRepository ChildItemRepository
{
get { return _childItemRepository ?? (_childItemRepository = new ChildItemRepository()); }
set { _childItemRepository = value; }
}

private IEnumerable<object> CreateObject(IEnumerable<Item> items)
{
List<object> objectList = new List<object>();
foreach (Item item in items)
objectList.Add(new { item.Name });
return objectList;
}

}

Now the three test cases
1. No id supplied the controller should return an empty result.
2. Supplied  with an invalide Guid the controller should return an empty result.
3. Supplied with a valid guid, the controller should return a JSon result with  the item names for all child items placed under the node with specified Guid,

Now for the Unit test class, as a mocking framework I’ve used NSubstitute. I’ve used the ItemStub I did in the this post Unit testing with Sitecore Item.  The code for this test Item is also as a service listet below.

public class ItemStub : Item
{
public ItemStub(string itemName)
: base(ID.NewID, new ItemData(new ItemDefinition(ID.NewID, itemName, ID.NewID, ID.NewID),Sitecore.Globalization.Language.Invariant, new Sitecore.Data.Version(1), new FieldList()), new Database("dummy"))
{
}

}

[TestFixture]
 public class ItemControllerTest
 {
 [Test]
 public void ItemControllWithNoIdShouldReturnEmptyList()
 {
 IChildItemRepository childItemRepositoryStub = Substitute.For<IChildItemRepository>();
 childItemRepositoryStub.Get(Arg.Any<string>()).Returns(new List<Item>());
 ItemController controller = new ItemController();
 controller.ChildItemRepository = childItemRepositoryStub;
 JsonResult result = controller.Index(string.Empty);
 Assert.That(result.Data,Is.Empty);
 }

[Test]
 public void ItemControllWithInvalideIDShouldReturnEmptyList()
 {

IChildItemRepository childItemRepositoryStub = Substitute.For<IChildItemRepository>();
 childItemRepositoryStub.Get(Arg.Any<string>()).Returns(new List<Item>());
 ItemController controller = new ItemController();
 controller.ChildItemRepository = childItemRepositoryStub;
 JsonResult result = controller.Index("invalidID");
 Assert.That(result.Data, Is.Empty);
 }

[Test]
 public void ItemControllWithValidIdShouldReturnJsonListWithItemNames()
 {
 IChildItemRepository childItemRepositoryStub = Substitute.For<IChildItemRepository>();
 List<Item> childList = new List<Item>();

childList.Add(new ItemStub("stub-a"));
 childList.Add(new ItemStub("stub-b"));
 childList.Add(new ItemStub("stub-c"));
 childList.Add(new ItemStub("stub-d"));

Guid itemGuid = Guid.NewGuid();
 childItemRepositoryStub.Get(itemGuid.ToString()).Returns(childList);
 ItemController controller = new ItemController();
 controller.ChildItemRepository = childItemRepositoryStub;
 JsonResult result = controller.Index(itemGuid.ToString());

List<object>resultData = (List<object>) result.Data; ;
 Assert.AreEqual(4,resultData.Count());
 Assert.AreEqual(resultData[0].ToString(),"{ Name = stub-a }");
 Assert.AreEqual(resultData[1].ToString(), "{ Name = stub-b }");
 Assert.AreEqual(resultData[2].ToString(), "{ Name = stub-c }");
 Assert.AreEqual(resultData[3].ToString(), "{ Name = stub-d }");
 }

And a screenshot of the test status.

I know that there probably exists better ways to test json results, but it is out of scope for this post, and yes if it should be “clean tests” each test should only contain one assert, but is left for as an exercise for you :).

In the next post we will extend Sitecore so that we can create Controllers through dependency injection, with Ninject as an IoC container. With this solution we don’t need the ugly Set in the Repository Property.

Sitecore MVC the first controller.

03/07/2012 1 comment

Sitecore 6.6 is now out, (as a technical preview), with the realse of this version Sitecore now offers full support for MVC. There have all ready been quite a few blog post how to user MVC with Sitecore and some of the new fetures offers a great deal of ease when developing with Sitecore.

So this is the first in a series of how to develop with Sitecore using MVC and some of the benefits you get for free using MVC.

If you haven’t allready read John West blog post on how to setup you Sitecore solution to use MVC you can read them here start with Part 1 and use part 3 to setup a visual studio solution .John also wrote some simple examples on how to use the MVC framework to return JSON serialized result from a controller you read his original post here. For a first post in this Sitecore MVC series we will revisit his example and create our own controller but with a different approach, and with the soon to be released .Net 4.5 Framework which include the new web-api this should be even easier, and given you even more flexibility for free and out of the box, we will look back at this example when the final release is out.

By now you should now have an up an running Sitecore 6.6 solution. My visual studio solution setup is shown below.

Now lets create our first controller Code listed below.


public class ItemController : Controller
 {

public JsonResult Index(string id)
 {
 return Json(CreateObject(ChildRepository.Get(parentItemId)), JsonRequestBehavior.AllowGet);
 }

private ChildItemRepository _childRepository;
 public virtual ChildItemRepository ChildRepository
 {
 get { return _childRepository ?? (_childRepository = new ChildItemRepository()); }

}

private IEnumerable<object> CreateObject(IEnumerable<Item> items)
 {
 foreach (Item item in items)
 yield return new {item.Name};
 }

}

With the controller in place you can change the route to newly created controller John in his example uses a Pipeline in Sitecore to achieve this i like this approache so much more the using the global.asax so we reuse his code for this with some minor alternations. The Id of the node we want to retrieve children for if not specified default to the id of the Home-node. I’ve done this because i don’t like all his assert for empty id, and if you don’t like you can just use the original approach with optional url parameter.You could if liked alsp default the index action. But instead of getting the id trough the url route data you should supply it as a argument to the action method. The key here is that parameter Id must be named the same as the input parameter in index method.


public class SitecoreMVCRoutes
 {

public virtual void Process(Sitecore.Pipelines.PipelineArgs args)
 {
 this.RegisterRoutes(RouteTable.Routes);
 }

public bool MvcIgnoreHomePage { get; set; }

protected virtual void RegisterRoutes(RouteCollection routes)
 {
 if (this.MvcIgnoreHomePage)
 {
 routes.IgnoreRoute(String.Empty);
 }

routes.MapRoute(
 "Default", // Route name
 "Item/{action}/{id}", // URL with parameters
 new { controller = "Item", action = "Index", id = "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}" } // Parameter defaults with Id to home node
 );
 }
 }

Now we will implement the busyness layer that will supply the controller with data.

This is done through a ChildRepository the code is listed below.

</pre>
public class ChildItemRepository
 {
 public virtual IEnumerable<Item> Get(string parentItemId)
 {
 ID parentId;
 if(ID.TryParse(parentItemId,out parentId))
 return GetChildNodes(parentId);
return new List<Item>();
 }

private IEnumerable<Item> GetChildNodes(ID parentId)
 {
 Item parentItem = Sitecore.Context.Database.GetItem(parentId);
 return parentItem.GetChildren();
 }
 }
<pre>

Lets test the new controller

First with out supplying a id,

Now with a valid id different form the home-node.

And now with a invalid id.

There we go the code does the same as Johns but with out all the assert tests.

Categories: .Net, C#, MVC, Sitecore 6, Uncategorized Tags: , ,

Loosely couple ninject kernel in MVC applications

27/07/2011 Leave a comment

I’m currently working on a hobby project “a photosite”, where I’m using MVC 3 with Entity Framwork 4 and Ninject IOC container. Maybe I overdid the decoupling of the Ninject kernel for this project, but I was fun to do and I gave material for this post :). The goal was to build a MVC project where the repository implementation was placed in separate project together with ninject binding.

So here is the repository Interaface:

public interface IGalleryRepository
{
   IEnumerable<Gallery> All { get; }
}

And here is the concrete implementation for the interface

public class GalleryRepository : IGalleryRepository
{
   PhotoSiteContext context = new PhotoSiteContext();
   public IEnumerable<Gallery> All
   {
    get { return context.Galleries; }
   }
}

Now we need to alter the global.asax file with the following.

public class MvcApplication : NinjectHttpApplication
{
   public static void RegisterGlobalFilters(GlobalFilterCollection filters)
   {
     filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Gallery", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();

AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
      {
var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
return kernel;
}
}

By loading the kernel this way Ninject will looke through all dll’s in the bin folder of MVC project “main project” and load all assemblies which inherit from the NinjectModul class.

Now we cant in same project as the implementation of the inteface make a new class which derives from Ninject modul. The class should look like this.

public class SqlCompactNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IGalleryRepository>().To<GalleryRepository>();
}
}
With this setup it would be possible to switch the gallery implementation simply by adding a new dll with a NinjectModule and a concrete implementation of the IgalleriInterface.
I hope you find this usefull.
Categories: .Net, MVC Tags: , , ,