Castle project


I have Google’d this and tried to find an answer to this error message for weeks.  I got a Error with controller lot of hits from Google but I couldn’t find the definitive answer to correct the error. I’m using Rhino.Commons as part of the application along with Castle project and NHibernate.

So I started a solution from scratch adding the stack components as I went. I got Castle IoC and MonoRail displaying a simple page. I added the Spark View Engine and still got the home/index.spark page to render. When I added the Rhino.Commons components that is when I got the error. That is when I finally had the ‘aha’ moment. All of the Google hits never gave me any real clue about what the problem was. Here is the definitive solution to the problem.

Once Rhino.Commons along with the IoC class is introduced you need to register the controllers. I never put this rather obvious conclusion in place because I wasn’t thinking it was caused by the Rhino.Commons IoC class. I kept looking at the web.config file and the controllers that were being registered there.

Here is how I registered the controller by placing this in the global.asax.cs file.

IoC.Container.Register(
                AllTypes.Of<IController>().FromAssemblyNamed("your controllers"));

All of my controllers extend SmartDispatcherController.

What directory structure should be used for a web based project? There are no hard, Application Structure fast rules for this. The opinions vary and even my typical website project has changed. This is the latest project directory organization that I am using.

There are three projects: Genealogist, Genealogist.Tests and Genealogist.Web. Genealogist.Web is an Add => New Project => Visual C# => Web => ASP.NET Web Application. Don’t use Add => New Web Site => ASP.NET Web Site. This will not play well with the Global.asax/Global.asax.cs file. The other two are just C# class library projects.

The Genealogist.Web application has a special directory, FrameStack. FrameStack itself has three directories: NHibernate, Spark and Windsor. All three have a class named ConfigurationByConvention. As the name implies each of these classes provide methods for configuring the 3rd party libraries without using .XML files.

The Genealogist project has two directories: DomainModel and Queries. More directories may be added in the future as the project is developed. For now YAGNI indicates that this is the minimum of what is needed.

The DomainModel is based on using DDD principles and the entities, value objects, factories and repositories will be created there. The Queries directory is something I added after reading Udi Dahan’s Employing the Domain Model Pattern in MSDN Magazine. It is a separation of read-only query support from the full CRUD requirements found in the DomainModel.

Web References The 3rd party DLLs I used are from the Castle, NHibernate and Spark View Engine open source projects. I’ll add the Rhino.Commons and Fluent NHibernate when I start developing the Domain Model.

Anyway this is my current web site application structure. It uses Castle Windsor and MonoRail along with the Spark View Engine.

I have played with three different approaches to configuring Rhino.Commons, NHibernate and Windsor container for unit testing. I’ve spiked these three flavors in order to investigate building an infrastructure that is open to extension but closed to modification. I’m still in the process of doing my analysis but I now have 3 approaches to  play with.

My last blog entry showed how to use Rhino.Commons with an in memory SQLite database. The example also used Windsor container and it was my initial proof of concept. There are lots of blogs like this but I still had trouble figuring out how to make this rather easy approach work.

Since then I have been refactoring this approach and making it more closely follow the Open-Closed Principle first coined in 1988 by Bertrand Meyer in his book, Object-Oriented Software Construction. Prentice Hall. ISBN 0136290493. There is a very good article on the ObjectMentor blog about the OCP.

The first refactor I did was move away from using the hibernate.cfg.xml file and do it NHibernate configuration dynamically. I did this by creating a ConventionConfiguration class that uses NHibernate.Cfg.Environment static class properties.

using NHibernate;
using Rhino.Commons;
using Configuration = NHibernate.Cfg.Configuration;
using Environment=NHibernate.Cfg.Environment;

namespace CrawBuck.Commons.NHibernate {
    public class ConventionConfiguration : Configuration {
        private readonly Configuration configuration = new Configuration();

        public Configuration getConfiguration() { return configuration; }

        /// <summary>
        /// This is the wiring up point for NHibernate. This sets up the Environment properties for
        /// SQLite in memory database
        /// </summary>
        public void ConfigureNHiberateForSQLite() {
            IDictionary<string, string> properties = new Dictionary<string, string>();
            properties.Add(Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider");
            properties.Add(Environment.ConnectionDriver, "NHibernate.Driver.SQLite20Driver");
            properties.Add(Environment.ConnectionString, "Data Source=:memory:;Version=3;New=True;");
            properties.Add(Environment.ShowSql, "true");
            properties.Add(Environment.Dialect, "NHibernate.Dialect.SQLiteDialect");
            properties.Add(Environment.ReleaseConnections, "on_close");
            properties.Add(Environment.ProxyFactoryFactoryClass, "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
            configuration.SetProperties(properties);
        }
    }
}

This class will only do two things right now. It will dynamically configure NHibernate to use SQLite and it will return the NHibernate.Cfg.Configuration variable that holds these properties. For my infrastructure work I will later add a method to dynamically configure MS SQL Server database. Unit testing should be fast but there are times when you actually have to hit a real database. I call real database testing ‘integration database testing’ and don’t have my continuous integration build machine run this type of testing at check in. I do want to do integration database testing but I set the build for this to happen at about 4 hour intervals. Currently I’m using CruiseControl.NET but I’m going to be moving to Hudson.

The next change I made was to move the configuration of the Windsor container to a class of its own, BinsorlessUnitOfWorkApplication. This is an extension of Rhino.Commons.HttpModules.UnitOfWorkApplication.

using System;
using Castle.Facilities.FactorySupport;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NHibernate;
using NHibernate.Cfg;
using Rhino.Commons;
using Rhino.Commons.HttpModules;
using Environment=System.Environment;

namespace CrawBuck.Commons.HttpModules {
    public class BinsorlessUnitOfWorkApplication : UnitOfWorkApplication {
        protected override IWindsorContainer CreateContainer(string windsorConfig) {
            //ignore windsor config string and create it empty…
            return new RhinoContainer();
        }

        /// <summary>
        /// This wires up the IoC Rhino/Windsor container for the basic facilities and components.
        /// </summary>
        public virtual void InitializeContainer() {
            Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
            IoC.Initialize(new WindsorContainer());
            IoC.Container
                .AddFacility<FactorySupportFacility>("factory.support")
                .AddFacility<RhinoTransactionFacility>("transaction")
                .Register(
                Component.For(typeof(IRepository<>)).ImplementedBy(typeof(NHRepository<>)),
                Component.For<IUnitOfWorkFactory>().ImplementedBy<NHibernateUnitOfWorkFactory>());
        }

        public void RegisterSessionFactory(Configuration configuration) {
            (IoC.Resolve<IUnitOfWorkFactory>() as NHibernateUnitOfWorkFactory).RegisterSessionFactory(configuration, configuration.BuildSessionFactory());
        }

        public ISessionFactory GetUnitOfWorkFactory() {
            return (IoC.Resolve<IUnitOfWorkFactory>() as NHibernateUnitOfWorkFactory).NHibernateSessionFactory;
        }
    }
}

I had to override the CreateContainer method in Rhino.Commons.HttpModules.UnitOfWork class to remove the need for the windsor.boo file. Once these two classes were in place I refactored the code from my last blog.

using System;
using System.Reflection;
using CrawBuck.Commons.HttpModules;
using CrawBuck.Commons.NHibernate;
using CrawBuck.Commons.Tests.Repository.Domain;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RhinoCommonsUnitOfWork {
        protected BinsorlessUnitOfWorkApplication unitOfWorkApplication = new BinsorlessUnitOfWorkApplication();
        protected ConventionConfiguration cc = new ConventionConfiguration();

        [SetUp]
        public void SetUp() {
            unitOfWorkApplication.InitializeContainer();
            cc.ConfigureNHiberateForSQLite();
            cc.getConfiguration().AddAssembly(Assembly.GetExecutingAssembly());
            unitOfWorkApplication.RegisterSessionFactory(cc.getConfiguration());
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer("Alan", "Buck");
            Guid guid = customer.Id;
            using(IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(cc.getConfiguration()).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, "Alan");
                Assert.AreEqual(loadCustomer.LastName, "Buck");
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq("Id", guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, "Alan");
                Assert.AreEqual(repositoryCustomer.LastName, "Buck");
            }
        }
    }
}

The following tests use either the Customer or Person classes.

using System;

namespace CrawBuck.Commons.Tests.Repository.Domain {
    public class Customer {
        private Guid id = Guid.NewGuid();
        private string firstName;
        private string lastName;

        public Customer() { }

        public Customer(string firstName, string lastName)
        {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public virtual Guid Id { get { return id; } set { id = value; } }
        public virtual string FirstName { get { return firstName; } set { firstName = value; } }
        public virtual string LastName { get { return lastName; } set { lastName = value; } }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-lazy=‘false’
    assembly=‘CrawBuck.Commons.Tests’
    namespace=‘CrawBuck.Commons.Tests.Repository.Domain’
    xmlns=‘urn:nhibernate-mapping-2.2′>
  <class name=‘Customer’>
    <id name="Id" column="Id">
      <generator class="assigned"/>
    </id>
    <property name="FirstName" />
    <property name="LastName"/>
  </class>
</hibernate-mapping>
using System;

namespace CrawBuck.Commons.Tests.Repository.Domain {
    public class Person {
        private Guid id = Guid.NewGuid();
        private string firstName;
        private string lastName;
        private int age;

        public Person() { }

        public Person(string firstName, string lastName, int age)
        {
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
        }

        public virtual Guid Id { get { return id; } set { id = value; } }
        public virtual string FirstName { get { return firstName; } set { firstName = value; } }
        public virtual string LastName { get { return lastName; } set { lastName = value; } }
        public virtual int Age { get { return age; } set { age = value; } }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-lazy=‘false’
    assembly=‘CrawBuck.Commons.Tests’
    namespace=‘CrawBuck.Commons.Tests.Repository.Domain’
    xmlns=‘urn:nhibernate-mapping-2.2′>
  <class name=‘Person’>
    <id name="Id" column="Id">
      <generator class="assigned"/>
    </id>
    <property name="FirstName" />
    <property name="LastName"/>
    <property name="Age" type="int"/>
  </class>
</hibernate-mapping>

The next refactor was to create a test base class that will allow the configuration of both the Windsor container and NHibernate using SQLite to be used by any unit test class.

using System;
using System.Reflection;
using CrawBuck.Commons.HttpModules;
using CrawBuck.Commons.NHibernate;
using CrawBuck.Commons.Tests.Repository.Domain;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RhinoCommonsUnitOfWork {
        protected BinsorlessUnitOfWorkApplication unitOfWorkApplication = new BinsorlessUnitOfWorkApplication();
        protected ConventionConfiguration cc = new ConventionConfiguration();

        [SetUp]
        public void SetUp() {
            unitOfWorkApplication.InitializeContainer();
            cc.ConfigureNHiberateForSQLite();
            cc.getConfiguration().AddAssembly(Assembly.GetExecutingAssembly());
            unitOfWorkApplication.RegisterSessionFactory(cc.getConfiguration());
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer("Alan", "Buck");
            Guid guid = customer.Id;
            using(IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(cc.getConfiguration()).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, "Alan");
                Assert.AreEqual(loadCustomer.LastName, "Buck");
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq("Id", guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, "Alan");
                Assert.AreEqual(repositoryCustomer.LastName, "Buck");
            }
        }
    }
}

Here is a unit test class that takes advantage of the RepositoryTestsBase class.

using System;
using CrawBuck.Commons.Tests.ForTesting;
using CrawBuck.Commons.Tests.Repository.Domain;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RepositoryTest : RepositoryTestsBase {
        private ISession session;
        private Person person;
        private Guid guid;

        [TestFixtureSetUp]
        public void TestFixtureSetUp() {
            OneTimeTestInitialize();
        }

        [SetUp]
        public void SetUp() {
            person = new Person("Alan", "Buck", 62);
            guid = person.Id;
        }

        [Test]
        public void ShouldCreateRepositoryTest() {
            session = CreateSession();
            session.Save(person);
            session.Flush();
            session.Clear();
            Person loadPerson = session.Load<Person>(guid);
            Assert.AreEqual(loadPerson.FirstName, "Alan");
            Assert.AreEqual(loadPerson.LastName, "Buck");
            Assert.AreEqual(loadPerson.Age, 62);
            session.Dispose();
        }

        [Test]
        public void ShouldCreateUsingIRepositoryTest() {
            using (IUnitOfWork uow = UnitOfWork.Start()) {
                new SchemaExport(configuration).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Person>.Save(person);
                uow.TransactionalFlush();
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Person)).Add(Restrictions.Eq("Id", guid));
                Person loadPerson = Repository<Person>.FindOne(criteria);
                Assert.AreEqual(loadPerson.FirstName, "Alan");
                Assert.AreEqual(loadPerson.LastName, "Buck");
                Assert.AreEqual(loadPerson.Age, 62);
            }
        }

        [TearDown]
        public void TearDown() {}
    }
}

That covers two of the approaches to using Rhino.Commons, NHibernate and the Windsor container. The last approach is to use FluentNHibernate. I’m not using the ClassMap of FluentNHibernate. This still uses the .hbm.xml files.

using System;
using System.IO;
using System.Reflection;
using Castle.Windsor;
using CrawBuck.Commons.HttpModules;
using CrawBuck.Commons.NHibernate;
using CrawBuck.Commons.Tests.Repository.Domain;
using FluentNHibernate.AutoMap;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;
using Configuration = NHibernate.Cfg.Configuration;
using Environment=NHibernate.Cfg.Environment;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class FluentNHibernate {
        private readonly BinsorlessUnitOfWorkApplication unitOfWorkApplication = new BinsorlessUnitOfWorkApplication();
        private Configuration config;
        private readonly ConventionConfiguration cc = new ConventionConfiguration();

        [SetUp]
        public void SetUp() {
            unitOfWorkApplication.InitializeContainer();
            cc.ConfigureNHiberateForSQLite();
            config = cc.getConfiguration();
            config.AddAssembly(Assembly.GetExecutingAssembly());
            CreateRhinoSessionFactoryForSQLite();
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer("Alan", "Buck");
            Guid guid = customer.Id;
            using (IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(config).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, "Alan");
                Assert.AreEqual(loadCustomer.LastName, "Buck");
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq("Id", guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, "Alan");
                Assert.AreEqual(repositoryCustomer.LastName, "Buck");
            }
        }

        private void CreateRhinoSessionFactoryForSQLite() {
            IPersistenceConfigurer configurer = SQLiteConfiguration.Standard.InMemory().ShowSql();
            ISessionFactory sessionFactory = Fluently.Configure(config).Database(configurer).Mappings(m => m.FluentMappings.AddFromAssemblyOf<Customer>()).BuildSessionFactory();
            (Rhino.Commons.IoC.Resolve<IUnitOfWorkFactory>() as NHibernateUnitOfWorkFactory).RegisterSessionFactory(config, sessionFactory);
        }
    }
}

You will notice that I have a CreateRhinoSessionFactoryForSQLite method in this test class. It’s there because I’m lazy and it’s late. Maybe in a future blog I will refactor this unit test to use ClassMap and move the CreateRhinoSessionFactoryForSQLite to the BinsorlessUnitOfWorkApplication class. I’m still moving up the learning curve on FluentNHibernate and have only the basic understanding of what all this OSS project has to offer.

I was attempting to write my first controller test using Castle.MonoRail.TestSupport class but was getting a System.TypeLoadException when I ran the unit test. So with some wasted hours trying to figure out what I was doing wrong I finally stumbled across a Castle forum topic that said the problem was caused by a “conflict of the trunk TestSupport’s assembly with the one in the GAC”. Removing the Castle.MonoRail.TestSupport dll from the GAC fixed it more me.

The first attempt at bringing together Brail and ExtJS was admittedly a little more than cut-and-paste. Now I want to create a simple page using Brail, ExtJS and the HomeController. One of the goals is to have a way to get most of the ExtJS scripting out of the Brail page and into a .js file. http://localhost:1999/home/BlowItAway.castle is the URL to get this to render in VS 2005.

Wizard1

I admit this doesn’t look like much but it is the beginning foundation that can be built upon to create what I hope will be a rich internet application. What I have done here is create a default.brail page that is analogous to a Master Page in ASP.NET. The default.brail page leverages a default.js file to reduce that amount of javascript that would normally be found between the <head></head> tags. I think this makes the default.brail page easier to understand.

   1: <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
   2: <html xmlns=“http://www.w3.org/1999/xhtml” >
   3: <head>
   4:     <title>Master Layout</title>
   5:     
   6:     <link rel=“stylesheet” type=“text/css” href=“../../Content/extJS/resources/css/ext-all.css” />
   7:     <!– GC –>
   8:     <!– LIBS –>
   9:     <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
  10:     <!– ENDLIBS –>
  11:     <script type=“text/javascript” src=“../../Content/extJS/ext-all.js”></script>
  12:     <script type=“text/javascript” src=“../../Content/js/default.js”></script>
  13:        
  14: </head>
  15: <body>
  16: <div id=“Banner”>Banner</div>
  17: <div id=“MainContent”>${ChildOutput}</div>
  18: <div id=“Footer”>Footer</div>
  19: </body>
  20: </html>

As you can see I have the <link> tag for the stylesheet location that I’m not really using at this time. There is also the ext-base.js and the ext-all.js script locations. Default.js allows me to move much of the code that is needed to support ExtJS into its own file.

   1: Ext.onReady(function(){
   2:     var banner = Ext.get(‘Banner’);
   3:     banner.setHeight(100);
   4:     banner.boxWrap();
   5:     var mainContent = Ext.get(‘MainContent’);
   6:     mainContent.setHeight(500);
   7:     mainContent.boxWrap();
   8:     var footer = Ext.get(‘Footer’);
   9:     footer.setHeight(25);
  10:     footer.boxWrap();
  11: }); 

Granted that this doesn’t do much now but the goal was to get it out off default.brail page and that goal has been met. I’m hoping to use this technique to build some generic RIA that will be reusable.

The HomeController is very simple right now too.

   1: using Castle.MonoRail.Framework;
   2:  
   3: namespace Genealogist.Controllers {
   4:     public class HomeController : SmartDispatcherController {
   5:         public void Index() {}
   6:  
   7:         [Layout(“default”)]
   8:         public void BlowItAway() {}
   9:     }
  10: }

BlowItAway.brail looks like this:

   1: Here it is

On the one hand I can’t believe it has taken me so long to get this far. I’m not sure if this is a reflection of my lack to intellect or the lack of good documentation. It’s probably more likely to be some combination of both. Being new to the Castle project (MonoRail, ActiveRecord, Windsor Container, Brail) and ExtJS definitely slows me down. I’m not new to MVC but so far their is very little MVC here.

Last night I left off with the creation of a Castle MonoRail template project and got it to display the ’sample demo’. Tonight I’m going to add ExtJS components to the project and remove the ’sample demo’ components from the project.

I blogged about ExtJS earlier with a link but what you also need to know is the licensing agreement. It comes in three flavors: Commercial, Open Source and OEM/Reseller. I’m not planning on commercializing the Genealogist project so I can go with the Open Source (GNU GPL license v3). At my day job we are seriously considering going with this and if our lawyers bless it we will be using the Commercial license.

This is what the Solution Explorer looks like after creating it using the Castle MonoRail Wizard3 project template.

I kept the files in the config directory but I opened the controllers.config file and deleted the login.controller and contact.controller components from the file. I kept the home.controller component.

In the Controllers directory I deleted the ContactController and the LoginController. I also deleted both files, ContactInfo.cs and Country.cs from the Models directory.

The Views directory had a Contact and Login directories that I deleted but I kept the Home, layouts and rescues directories.

In the layouts directory I replaced the existing code in the default.brail file with ExtJS code from the Writing a Big Application in ExtJS tutorial.

   1: <html>
   2: <head>
   3:   <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8″>
   4:   <link rel=“stylesheet” type=“text/css” href=“../../Content/ext/resources/css/ext-all.css”>
   5:   <link rel=“stylesheet” type=“text/css” href=“../../Content/css/application.css”>
   6:   <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
   7:   <script type=“text/javascript” src=“../../Content/extJS/ext-all-debug.js”></script>
   8:   <script type=“text/javascript” src=“../../Content/js/application.js”></script>
   9:   <title>A Big Application</title>
  10: </head>
  11: <body>
  12:     <div>Banner</div>
  13:     <div>MainContent</div>
  14:     <div>Footer</div>
  15: </body>
  16: </html>

The Default.aspx page has no code behind and only contains a script section that overrides the OnLoad event of the page lifecycle.

   1: <%@ Page Language=“C#” %>
   2: <script runat=“server”>
   3:   protected override void OnLoad(EventArgs e)
   4:   {
   5:     Response.Redirect(“~/home/index.castle”);
   6:     base.OnLoad(e);
   7:   }
   8: </script>

Even though this redirects to the ~/home/index.castle page the ~/layout/default.brail page gets run and there is no content holder, ${ChildOutput}, to render the ~/home/index.brail page in. So what is rendered is this:

Wizard2

If you’re paying attention you will notice that the redirect is to ~/home/index.castle and there is no ~/home/index.castle file. This confused me at first until I realized that in the web.config file this section mapped the .castle extension to the .brail extension.

   1: <httpHandlers>
   2:     <add verb=“*” path=“*.castle” type=“Castle.MonoRail.Framework.MonoRailHttpHandlerFactory, Castle.MonoRail.Framework” />
   3:     <!– block direct user access to template files –>
   4:     <add verb=“*” path=“*.vm” type=“System.Web.HttpForbiddenHandler” />
   5:     <add verb=“*” path=“*.njs” type=“System.Web.HttpForbiddenHandler” />
   6:     <add verb=“*” path=“*.brail” type=“System.Web.HttpForbiddenHandler” />
   7:     <add verb=“*” path=“*.brailjs” type=“System.Web.HttpForbiddenHandler” />
   8:     <add verb=“*” path=“*.st” type=“System.Web.HttpForbiddenHandler” />
   9: </httpHandlers>

You can replace the path=”*.castle” with whatever you want as the extension and it will map the extensions: .vm, .nis, .brail, .brailjs and .st to it.

For a long time in my software career I made the statement, “I don’t do no stinkin’ UI”. The UI I just rendered above shows how little I know about UI but at this point I’m going to start working with .css and images and other UI components. This is just the start.

I am going to use the latest CastleProject-1.0-RC3.msi to create my Genealogy project. I’m going to name it Genealogist. I had started a Genealogy project before but I decided to begin afresh. I was attempting to convert what I had started but it just got messy with the configuration issues that kept popping up.

After installing the Castle Project RC3, start up Visual Studio (I’m still using VS 2005) and create a new project using the Castle MonoRail template. I’m naming it Genealogist.

CreateProject

I’m choosing to use the Brail View Engine and enabling Windsor (inversion of control container) but I’m not enabling URL routing module at this time.

Wizard1

I’m going to be using ActiveRecord, Automatic Transaction Management and Logging.

Wizard2

Naturally I’m a TDD enthusiast!

Wizard3

ActiveRecord assemblies will be contained in the Genealogist Assembly.

Wizard4

I’m going to be using MySql.

Wizard5

Finally I’m going to be using Log4Net as my Logging type.

Wizard6

I let this churn and I end up with a MonoRail project that has IoC/DI, logging, MonoRail and ActiveRecord all ready configured. I hit the green arrow go button in VS2005 and I get a working web application.

Wizard7

How cool is that!

I’m going to make changes to this and get rid of the ‘template’ application but I don’t have to go through all of the difficult configuration issues. If you remember I’m also going to use ExtJS. So I’ve still got a lot to do before I have the beginnings of my ‘home project’.

I’m going to be using MonoRail and ActiveRecord from the Castle project so the first thing I need to do is get them configured. I’m also going to be using MySql as the database so I need to download and install it.

I’ve decided to add a Config directory to my Genealogy website so I need to tell how to locate these files in web.config. I need to indicate a castle configuration section by adding to the <configSections>.

<configSections>
    <section name=“castle”
             type=“Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor” />
</configSections>

Then below <system.web> I add a <castle> section.

<castle>
    <include uri=“file://Config//properties.config” />
    <include uri=“file://Config//facilities.config” />
    <include uri=“file://Config//controllers.config” />
    <include uri=“file://Config//components.config” />
</castle>

This is the preliminary configuration to use MonoRail and ActiveRecord. You notice that I’ve also configured logging.

The facilities.config file holds the ActiveRecord and Windsor container configuration. One gotcha that I found was that I also need to add my Genealogy assembly to this file. It goes in the <facility> section.

<assemblies>
    <item>Genealogy</item>
</assemblies>

The first thing I need to do is set up a HomeController but I blog that later.

I was toying with the idea of writing about build a Genealogy project using the Castle stack. However there are lots of other blogs that have lots of other examples of building projects off the Castle stack. So it seems kind of redundant for me to add other sample project. Instead I’ve decided to follow Ben Lovell’s blog where he is building a blog engine using the Castle stack. You can read about it yourself at .net and other musings.

I have already written about my day job letting the development team switch over to the Castle stack and my success at getting data from the database up through ActiveRecord - MonoRail - Brail. It looks like we’re going to be using a slight variation to this with ExtJS - MonoRail - ActiveRecord/Rhino Commons as the stack. So my Genealogy project is going to use the same stack.

I’ll be blogging about how this will diverge from Ben’s Blog Engine as I make progress on my project.

I have been using .NET 2.0 and the MVP design pattern to write software for my day job. Last week I was presented with a pleasant surprise. The PM has said that it is okay for myself and some others to investigate a new stack for software delivery.

We’re now getting to charge forward in our investigation of using the Castle Project stack. So for two days I was trying to get the Castle stack up and working. My investigation centered on using Brail as the ViewEngine with MonoRail and ActiveRecord to display actual data from the database in a grid format in the UI.

Well I tried to do this by living off the trunk for both NHibernate and Castle source code. While I didn’t have any problem with NHibernate I have already blogged about my issues building the Castle components. I was successful with building the Castle components but I was having trouble getting the whole stack to work. I finally abandoned the latest-greatest from the trunk code and got the RC3 binaries for the Castle Project.

I was then able to actually get data from the database and transferred up through ActiveRecord/MonoRail and displaying in a grid rendered with Brail. This was great.

One of the other team members was using ExtJS as the ViewEngine with MonoRail and Rhino Commons and NHibernate to do the same thing. He was a day behind me in accomplishing this because he was building the latest-greatest from the trunks of these projects and had trouble getting Rhino Commons to play well with the latest-greatest NHibernate/Castle project components.

He did get it done and also extended the Rhino Commons components to implement an IFutureRepository<T> methodology that would bring back multiple queries with one roundtrip to the database.

On Wednesday after my Tuesday success with Brail-MonoRail-ActiveRecord I began a brand new investigation into EDA (event driven architecture). So for the next few days I’m going to be prototyping SEDA (staged event driven architecture). I’ll write about that later.

Next Page »