Genealogy project


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’ve been busy on a SP1 release for the my day job and haven’t spent much time on figuring out ExtJS. I’ve blogged before about how I am having difficulty coming up to speed on this product. I have been trying for weeks to use the pre-configured concept of ExtJS without success. ExtJS’s examples show very simple usages and I’m trying to make use more complex usages. So it has been a lot of trial and run. I’ve finally got the accordion panel to work outside of my Genealogist layout and I’m going to try and incorporate it. Here is how it looks:

Wizard1

This has the accordion panel on the left and the right panel can be used for multiple purposes. The goal is to have the accordion panel expose the various functions of the Genealogist project and the right panel will provide the implementation of the functions. I’m going to incorporate this into the Genealogist layout:

Wizard2

I’m using the pre-configured classes that are talked about here. The general pattern is:

   1: MyScope = Ext.extend(Ext.form.ComboBox, {
   2:     // configurables
   3:     // anything what is here can be configured from outside
   4:      border:false
   5:  
   6:     // {{{
   7:     ,initComponent:function() {
   8:         // {{{
   9:         Ext.apply(this, {
  10:             // anything here, e.g. items, tools or buttons arrays,
  11:             // cannot be changed from outside
  12:         }); // e/o apply
  13:         // }}}
  14:  
  15:         // call parent
  16:         MyScope.superclass.initComponent.apply(this, arguments);
  17:  
  18:         // after parent code here, e.g. install event handlers
  19:  
  20:     } // e/o function initComponent
  21:     // }}}
  22:     // {{{
  23:     ,onRender:function() {
  24:  
  25:         // before parent code
  26:  
  27:         // call parent
  28:         MyScope.superclass.onRender.apply(this, arguments);
  29:  
  30:         // after parent code, e.g. install event handlers on rendered components
  31:         
  32:     } // e/o function onRender
  33:     // }}}
  34:     
  35:     // any other added/overrided methods
  36:  
  37: }); // e/o extend
  38:  
  39: // register xtype
  40: Ext.reg(‘mycomponentxtype’, MyScope); 

I’m using a single file for the AccordionPanel class and the code is:

   1: Ext.ux.AccordionPanel = Ext.extend(Ext.Panel, {
   2:     region:‘west’,       
   3:     margins:‘5 0 5 5′,
   4:     split:true,
   5:     width: 210,
   6:     layout:‘accordion’,
   7:         
   8:     initComponent: function(){
   9:         Ext.apply(this, {
  10:             items:[{
  11:                 title: ‘Accordion Item 1′,
  12:                 html: ‘<empty panel>’,
  13:                 xtype: ‘panel’
  14:             },{
  15:                 title: ‘Accordion Item 2′,
  16:                 html: ‘<empty panel>’,
  17:                 xtype: ‘panel’
  18:             },{
  19:                 title: ‘Accordion Item 3′,
  20:                 html: ‘<empty panel>’,
  21:                 xtype: ‘panel’
  22:             },{
  23:                 title: ‘Accordion Item 4′,
  24:                 html: ‘<empty panel>’,
  25:                 xtype: ‘panel’
  26:             },{
  27:                 title: ‘Accordion Item 5′,
  28:                 html: ‘<empty panel>’,
  29:                 xtype: ‘panel’
  30:             }]
  31:         });
  32:         
  33:         Ext.ux.AccordionPanel.superclass.initComponent.apply(this, arguments);
  34:     },
  35:     
  36:     onRender:function(){
  37:         Ext.ux.AccordionPanel.superclass.onRender.apply(this, arguments);
  38:     }
  39:  
  40: });
  41:  
  42: Ext.reg(‘accordionPanel’, Ext.ux.AccordionPanel);

The .brail page looks like this:

   1: <html>
   2: <head>
   3:     <title>Accordion Layout</title>
   4:     <link rel=”stylesheet” type=”text/css” href=”../../Content/ExtJS/resources/css/ext-all.css”/>
   5:  
   6:     <!– GC –>
   7:     <!– LIBS –>
   8:     <script type=”text/javascript” src=”../../Content/ExtJS/adapter/ext/ext-base.js”></script>
   1:  
   2:     <!– ENDLIBS –>
   3:  
   4:     <script type=“text/javascript” src=“../../Content/ExtJS/ext-all-debug.js”>
   1: </script>
   2:     <script type=“text/javascript” src=“../../Content/ExtJS/js/AccordionPanel.js”>
   1: </script>
   2:  
   3:     <style type=“text/css”>
   4:         html, body {
   5:             font: normal 12px verdana;
   6:             margin: 0;
   7:             padding: 0;
   8:             border: 0 none;
   9:             overflow: hidden;
  10:             height: 100%;
  11:         }
  12:         .empty .x-panel-body {
  13:             padding-top:20px;
  14:             text-align:center;
  15:             font-style:italic;
  16:             color: gray;
  17:             font-size:11px;
  18:         }
  19:     </style>
  20:     <script type=“text/javascript”>
  21:         Ext.onReady(function() {
  22:                         
  23:             var viewport = new Ext.Viewport({
  24:                 layout:‘border’,
  25:                 renderTo:Ext.getBody(),
  26:                 items:[{
  27:                     xtype:‘accordionPanel’
  28:                 },{
  29:                     region:‘center’,
  30:                     margins:‘5 5 5 0′,
  31:                     cls:‘empty’,
  32:                     bodyStyle:‘background:#f1f1f1′,
  33:                     html:‘<br/><br/>&lt;empty center panel&gt;’
  34:                 }]
  35:             });
  36:             
  37:         });
  38:     

</script>

   9: </head>
  10: <body>
  11:  
  12: </body>
  13: </html>

I can’t believe it has taken me this long to do this. I still don’t understand ExtJS very well but I’m slowly picking up pieces. My hope is that starting this week I will be able to spend my day job increasing my understanding of ExtJS.

I started down this path to create a genealogy project inspired by Ben Lovell’s ‘Incremental development with Monorail’ postings. So I’m now completing my first page based on his Part One.

I’m deviating somewhat from this first part in that I’m dividing my unit tests into two types of tests: unit and integration. In my Genealogist.Tests I have Controllers directory where I place the PersonController tests. The Integration directory is where I place the PersonControllerIntegration tests.

Wizard3

PersonControllerTest contains the first test, ShouldRenderAddPersonForm. This extends the BaseControllerTest class from the Castle.MonoRail.TestSupport assembly. I had trouble getting this to work and it turned out that I have an old version of the Castle.MonoRail.TestSupport assembly down in the GAC. Once I removed it then the test worked.

   1: using Castle.MonoRail.TestSupport;
   2: using Genealogist.Controllers.Persons;
   3: using NUnit.Framework;
   4:  
   5: namespace MRProjectTest.Controllers {
   6:     [TestFixture]
   7:     public class PersonControllerTest : BaseControllerTest {
   8:         private PersonsController personController;
   9:  
  10:         [SetUp]
  11:         public void SetUp() {
  12:             personController = new PersonsController();
  13:             PrepareController(personController,@”Persons”, “addPerson”);
  14:         }
  15:  
  16:         [Test]
  17:         public void ShouldRenderAddPersonForm() {
  18:             personController.Add();
  19:             Assert.IsNotNull(personController);
  20:             Assert.AreEqual(personController.SelectedViewName, @”Personsadd”, @”Expected view: PersonAdd wasn’t rendered”);
  21:         }
  22:  
  23:         [TearDown]
  24:         public void Teardown() {}
  25:     }
  26: }

PersonControllerIntegrationTest contains the first test, ShouldRenderAddPersonForm. This is the first time I have used WatiN. All it took was to add two references to my project: WatiN.Core and Interop.SHDocVw. I had a small issue here getting the test to work because I used http://localhost:16489/Persons/add.brail. Once I changed it to http://localhost:16489/Persons/add.castle the test worked.

   1: using NUnit.Framework;
   2: using Rhino.Mocks;
   3: using WatiN.Core;
   4:  
   5: namespace MRProjectTest.Integration {
   6:     [TestFixture]
   7:     public class PersonControllerIntegrationTests {
   8:         private MockRepository mock;
   9:  
  10:         [SetUp]
  11:         public void SetUp() {
  12:             mock = new MockRepository();
  13:         }
  14:  
  15:         [Test]
  16:         public void ShouldRenderAddForm() {
  17:             using (IE browser = new IE(“http://localhost:16489/Persons/add.castle”)) {
  18:                 Assert.IsTrue(browser.ContainsText(“Add Person”));
  19:             }
  20:         }
  21:  
  22:         [TearDown]
  23:         public void TearDown() {
  24:             mock.VerifyAll();
  25:         }
  26:     }
  27: }

Using TDD both of these test failed but with some small amount of code both of these succeed. The PersonsController code is:

   1: using Castle.MonoRail.Framework;
   2:  
   3: namespace Genealogist.Controllers.Persons {
   4:     public class PersonsController : Controller {
   5:         [Layout(“default”)]
   6:         public void Add() {
   7:             RenderView(“add”);
   8:         }
   9:     }
  10: }

The add.brail code is this:

   1: Add Person

Be sure to add the Person controller to the controllers.config file. I forgot to and it took me a couple of minutes to figure out why it wasn’t working.

   1: <?xml version=“1.0″ encoding=“utf-8″?>
   2: <configuration>
   3:     <components>
   4:         <component id=“home.controller” type=“Genealogist.Controllers.HomeController, Genealogist” />
   5:     <component id=“persons.controller” type=“Genealogist.Controllers.Persons.PersonsController, Genealogist” />
   6:     </components>
   7: </configuration>

When it is all said and done I got this:

Wizard2

While this doesn’t seem like much it is the beginnings of something that has taken me hours to understand. All of the Castle stack is in place and I’m using ExtJS to help with the rendering of the page using the Brail ViewEngine. This is good.

Last week I had visitors from out of town so I didn’t get much time to work on this when I came home. I now have a final layout that I will work from.

Wizard1

The default.brail file is this:

   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:     <link rel=“stylesheet” type=“text/css” href=“../../Content/extJS/resources/css/genealogist.css” />
   8:     <!– GC –>
   9:     <!– LIBS –>
  10:     <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
  11:     <!– ENDLIBS –>
  12:     <script type=“text/javascript” src=“../../Content/extJS/ext-all.js”></script>
  13:     <script type=“text/javascript” src=“../../Content/js/default.js”></script>
  14:        
  15: </head>
  16: <body>
  17: <div id=“Banner”>Genealogist</div>
  18: <div id=“MainContent”>
  19:     <table id=“MainContentTable”>
  20:         <tr>
  21:             <td id=“FunctionPanel”></td>
  22:             <td id=“DisplayContent”>${ChildOutput}</td>
  23:         </tr>
  24:     </table>
  25: </div>
  26: <div id=“Footer”>CrawBuck Copyright 2008</div>
  27: </body>
  28: </html>

The genealogist.css is this:

   1: body
   2: {
   3: }
   4: #Banner
   5: {
   6:     background-image:url(../images/BannerBackground.png);
   7:     background-repeat:repeat-x;
   8:     border:solid 1px #1D6241;
   9:     text-align:right;
  10:     vertical-align:middle;
  11:     padding-right:10px;
  12:     font-family:Georgia;
  13:     font-size:75px;
  14:     color:#ED7014;
  15: }
  16: #MainContent
  17: {
  18:     height:654px;
  19: }
  20: #Footer
  21: {
  22:     background-image:url(../images/FooterBackground.png);
  23:     background-repeat:repeat-x;
  24:     border:solid 1px #1D6241;
  25:     text-align:center;
  26:     font-family:Verdana;
  27:     font-weight:bold;
  28:     color:#ED7014;
  29:     padding-top:5px;
  30: }
  31: #MainContentTable
  32: {
  33:     width:100%;
  34:     height:100%;
  35: }
  36: #FunctionPanel
  37: {
  38:     width:20%;
  39:     border:solid 1px Black;
  40: }
  41: #DisplayContent
  42: {
  43:     width:80%;
  44:     border:solid 1px Black;
  45: }

Nothing real fancy but it will allow me to start building on the Castle stack using ExtJS.

I’ve worked on the CSS for the Genealogist and have added it to the Banner portion of the page. I added a new Genealogist.css file:

   1: #Banner
   2: {
   3:     background-image:url(../images/BannerBackground.png);
   4:     background-repeat:repeat-x;
   5:     border:solid 1px #1D6241;
   6:     text-align:right;
   7:     vertical-align:middle;
   8:     padding-right:10px;
   9:     font-family:Georgia;
  10:     font-size:75px;
  11:     color:#ED7014;
  12: }

and now it looks like this:

Wizard1

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.

There isn’t a lot of good documentation on how to pair up Brail View Engine with ExtJS. Through experimenting I have gotten this to show up in the Firefox browser:

Wizard1

This is done by redirecting from the Default.aspx page to ~/home/index.castle in the OnLoad event.

The code for the Default.aspx page is:

 

 

   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>

The code for the index.brail page is basically a cut-and-paste for the ExtJS ext-2.1/examples/layout/complex.html. I did have to do some modification to make it work with my directory structure. My directory structure for the ExtJS files looks like this:

Wizard1

The /adapter directory contains the ext-base.js. I have the cascade style sheets and the images in the resource directory. I had to add the examples.js file to the Content/js directory.

I ended up making modification to all of the ’src=’ references in the script tags to point to these locations.

 

 

   1: <link rel=“stylesheet” type=“text/css” href=“../../Content/extJS/resources/css/ext-all.css” />
   2: <!– GC –>
   3: <!– LIBS –>
   4: <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
   5: <!– ENDLIBS –>
   6:
   7: <script type=“text/javascript” src=“../../Content/extJS/ext-all.js”></script>

The HomeController code just had an empty Index() method. It took me about 1 hour to figure this out.

There are a lot of little pieces to use ExtJS. I still need to understand how it all fits together. I’ll work on that next.

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 use ExtJS in the Genealogy project. In their words, “Ext JS is a cross-browser JavaScript library for building rich Internet applications.” We’re going to be using this at my day job so I thought I would include it with the night/weekend play job.

To that extent there is a tutorial I’ll be following named Writing a Big Application in Ext.

Next Page »