First of all, I just pushed to Nuget two code-only packages in addition to Jose.MVC.Windsor:
- Jose.SessionPerRequest.NHibernate: the code of my previous post Effective NHibernate Session management for web apps.
- Jose.DataAccessObjects.NHibernate: some simple DataAccessObject that I use most of the time.
For this example I’d use the Chinook sample database.
Start a new project:
Then, I’d use the following nuget packages:
- Jose.MVC.Windsor; this install the basic artifacts to working with Castle.Windsor in Asp.Net MVC.
- Jose.SessionPerRequest.NHibernate; base classes to work with the Session Per Request pattern.
- Jose.DataAccessObject.NHibernate; interface and implementation of a simple data access object.
Within Visual Studio you can use the Add Library Package Reference or the Package Manager Console, the output will be like this:
PM> install-package Jose.MVC.Windsor 'Castle.Windsor (≥ 2.5.2)' not installed. Attempting to retrieve dependency from source... Done 'Castle.Core (≥ 2.5.2)' not installed. Attempting to retrieve dependency from source... Done 'WebActivator (≥ 1.4)' not installed. Attempting to retrieve dependency from source... Done Successfully installed 'Castle.Core 2.5.2' Successfully installed 'Castle.Windsor 2.5.2' Successfully installed 'WebActivator 1.4' Successfully installed 'Jose.MVC.Windsor 1.0.0' Successfully added 'Castle.Core 2.5.2' to ChinookWithNugets Successfully added 'Castle.Windsor 2.5.2' to ChinookWithNugets Successfully added 'WebActivator 1.4' to ChinookWithNugets Successfully added 'Jose.MVC.Windsor 1.0.0' to ChinookWithNugets PM> install-package Jose.SessionPerRequest.NHibernate 'NHibernate (≥ 3.0.0)' not installed. Attempting to retrieve dependency from source... Done 'Iesi.Collections (≥ 1.0.1)' not installed. Attempting to retrieve dependency from source... Done 'Antlr (≥ 3.1.3.42154)' not installed. Attempting to retrieve dependency from source... Done Successfully installed 'Iesi.Collections 1.0.1' Successfully installed 'Antlr 3.1.3.42154' 'Castle.Core 2.5.2' already installed Successfully installed 'NHibernate 3.0.0.2001' Successfully installed 'Jose.SessionPerRequest.NHibernate 1.0.0' Successfully added 'Iesi.Collections 1.0.1' to ChinookWithNugets Successfully added 'Antlr 3.1.3.42154' to ChinookWithNugets ChinookWithNugets already has a reference to 'Castle.Core 2.5.2' Successfully added 'NHibernate 3.0.0.2001' to ChinookWithNugets Successfully added 'Jose.SessionPerRequest.NHibernate 1.0.0' to ChinookWithNugets PM> install-package Jose.DataAccessObjects.NHibernate 'Iesi.Collections 1.0.1' already installed 'Antlr 3.1.3.42154' already installed 'Castle.Core 2.5.2' already installed 'NHibernate 3.0.0.2001' already installed Successfully installed 'Jose.DataAccessObjects.NHibernate 1.0.0' ChinookWithNugets already has a reference to 'Iesi.Collections 1.0.1' ChinookWithNugets already has a reference to 'Antlr 3.1.3.42154' ChinookWithNugets already has a reference to 'Castle.Core 2.5.2' ChinookWithNugets already has a reference to 'NHibernate 3.0.0.2001' Successfully added 'Jose.DataAccessObjects.NHibernate 1.0.0' to ChinookWithNugets
Now you need to do some manual steps:
1-Fix the registration of the HttpModules in the web.config to something like this:
<add name="SessionPerRequest" type="ChinookWithNugets.Infrastructure.SessionManagement.NHibernateSessionModule, ChinookWithNugets" />
2-Add a new connection string in the web.config:
<configuration>
<appSettings>
.....
</appSettings>
<connectionStrings>
<add name="Chinook" connectionString="Server=.\sqlexpress; User=test; Password=test; Database=Chinook" />
</connectionStrings>
....
3-Create an installer for Daos, in Infrastructure\Installers\ , the code as follows:
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using ChinookWithNugets.Data;
namespace ChinookWithNugets.Infrastructure.Installers
{
public class DaoInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For(typeof (IDao<>))
.Forward(typeof (IDaoReadOnly<>))
.ImplementedBy(typeof (Dao<>)));
}
}
}
4-Create an installer for NHibernate:
using System.Collections.Generic;
using System.Web;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using ChinookWithNugets.Infrastructure.SessionManagement;
using NHibernate;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;
using NHibernate.Cfg.Loquacious;
using NHibernate.Dialect;
namespace ChinookWithNugets.Infrastructure.Installers
{
public class NHibernateInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<ISessionFactory>()
.UsingFactoryMethod(k => BuildSessionFactory()));
container.Register(Component.For<ISessionFactoryProvider>().AsFactory());
container.Register(Component.For<IEnumerable<ISessionFactory>>()
.UsingFactoryMethod(k => k.ResolveAll<ISessionFactory>()));
HttpContext.Current.Application[SessionFactoryProvider.Key]
= container.Resolve<ISessionFactoryProvider>();
}
private ISessionFactory BuildSessionFactory()
{
var configuration = new Configuration();
configuration.DataBaseIntegration(db =>
{
db.Dialect<MsSql2008Dialect>();
db.ConnectionStringName = "Chinook";
});
configuration.Properties[Environment.CurrentSessionContextClass]
= typeof (LazySessionContext).AssemblyQualifiedName;
configuration.Proxy(p => p.ProxyFactoryFactory<ProxyFactoryFactory>());
configuration.AddAssembly(GetType().Assembly);
return configuration.BuildSessionFactory();
}
}
}
5-Create the Album class in
namespace ChinookWithNugets.Domain
{
public class Album
{
public string Title { get; set; }
}
}
6-Create a mapping for albums Album.hbm.xml in "Data\Mappings":
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="ChinookWithNugets.Domain"
assembly="ChinookWithNugets">
<class name="Album">
<id column="AlbumId">
<generator class="identity" />
</id>
<property name="Title" />
</class>
</hibernate-mapping>
7-Create a HomeController in the Controllers folder:
using System.Linq;
using System.Web.Mvc;
using ChinookWithNugets.Data;
using ChinookWithNugets.Domain;
namespace ChinookWithNugets.Controllers
{
public class HomeController : Controller
{
private readonly IDao<Album> daoAlbums;
public HomeController(IDao<Album> daoAlbums)
{
this.daoAlbums = daoAlbums;
}
public ActionResult Index()
{
var albums = daoAlbums.RetriveAll().ToList();
return View(albums);
}
}
}
8-Create a Index view in Views\Home:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<List<ChinookWithNugets.Domain.Album>>" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<ul>
<% foreach(var a in Model) { %>
<li><%= a.Title %></li>
<% } %>
</ul>
</body>
</html>
9-Run! you have now a sample ASp.Net MVC application with NHibernate and Castle.Windsor fully integrated.
If you want to see the full code; it is here.
IMPORTANT NOTE: unfortunately now you have to do an extra step, regarding internals stuff of the NHibernate project. Install the NHibernate.Castle package…
