Mike Nichols - Son of Nun Technology

August 2007 Entries

SetResultTransformer for DTOs in NHibernate

I had some difficulty finding a good example of SetResultTransformer for an ICriteria for NHibernate. Here's a good one that helped me. Also has a good example of using aliases. I get confused when working with the semantics of ICriteria but it is really quite powerful for creating dynamic queries.

NHibernate ICriteria Duplicate table alias problem

 

I was constructing a ICriteria with aliases and kept getting a duplicate join in my FROM clause of the output sql with the error 'table names must be unique'. Here's the fixins on the criteria:

 

crit.CreateAlias("max.Sample", "s")

                    .CreateAlias("s.Project", "proj")

                    .CreateAlias("s.Project.EnterpriseProject", "entProj")

                    .CreateAlias("s.MaterialCode", "mc");

 
The problem was the 'mc' alias that kept producing 3 different joins that were equal. Finally I looked into my mapping and since I am mapping to an interface I had <subclass>ed implementations of the interface. Now since I am using access strategy 'nosetter' I was forced to repeat the mapping for the MaterialCode property in each concrete mapping. There are 3 implementations. Thus, when Hibernate created the sql it was creating the join to the materialCode (mc) three times.
To fix it I am forced to include a setter  on the MaterialCode property and declare it in the interface.
Problem solved.
 

Back From Vacation - La Jolla, California

Just got back from week's vacation at La Jolla, California. It was great as we got a little cabin just up from the beach and my wife got a well-deserved break. My children saw the ocean for the first time - if I had to draw a picture of joy I'd draw my daughter (2 1/2 years old) as we splashed in the tidepools that are common along that part of the coast. The infinite creativity of Christ that's made obvious by all these creatures is really a treat .

La Jolla. just outside of San Diego, is highly recommended....typically I prefer more private places but this was a nice little treat with tons of fun things to do.

Constructor signatures ,dependency enforcement, and the Factory

When taking a first swim into Object Oriented principles, there seems to be an implicit rule that your constructor signatures should be based upon what is required for a valid object to be created.

The purist in me resonates with this, but the wet-behind-the-ears TDD guy discovers that he hates that purist guy. I want to be able to TEST without having to create a ton of mock objects to simply get my object created.

Take these two classes:

 

public class ClassA
{
    public ClassA(){}
}

public class ClassB
{
    private ClassA classA; 
   public ClassB(ClassA classA){ this.classA = classA;}
    public ClassA
    {
      get{return classA;} // no setter since this is required
    }

}

Now this is harmless and I could mock ClassA somehow and be just fine. But if ClassA has constructor dependencies and then those dependencies have constructor dependencies we'll want to find a way to mock INSANITY.

There are a couple of thing to do with this:

  • Accept that Object Oriented principles are the most important driver in the decision making process ... so grin and write all your mocks.
  • Place a setter for properties which are NOT optional

So let's choose to add a setter on ClassA property in ClassB class. Now we've opened ourself up to integrity issues right? I can smell the strong aroma of NullReferenceExceptions from my keyboard.

But this is where DDD principles come in to harmonize with TDD pragmatism with the Factory and Aggregate patterns. Rather than 'new'-ing just anywhere in your application, DDD specifies that object creation and its variants (dependents) are encapsulated in a Factory. With this rule in place we can now loosen the constructor constraint we had on ClassB and provide a default (no-arg) constructor with a setter for the required properties.

My presenters or whereever else I need to fetch my aggregate object are REQUIRED to go to my factory for an object and this way I can push my dependency requirements THERE rather than on the object itself.

Now, really I want to force dependencies as much as possible into my constructor so I won't  altogether avoid having parameters in my constructors. But the factory pattern allows us to both control how objects are created and enforcing dependencies, while freeing up testing scenarios by reducing the amount of mocking/stubbing required.

Visual Studio Quick Tip - Close ErrorList, Output, Whatever

The command is Window.CloseToolWindow and defaults to Shft+Esc.

I can't STAND the intrusive ErrorList so now I can zap it away...took me forever to find this one.

MSBuild hbm2ddl task...almost

I have completed the port of the NAnt NHibernate.Task hbm2Ddl to MSBuild. I used this to learn how MSBuild works and it works great but only if the assembly that is used for NHibernate to inspect is in the /bin folder where the task .dll is running. IT tells me that it can't find the class associated with the .hbm.xml. I know for a fact that the assembly it is inspecting is just fine so it has something to do with MSBuild while running a task.

Within the task, I use the 'AddAssembly' method to .. er..add the assembly and that's where it bombs .

Anything I need to understand more about MSBuild to get this task going? The Nant task works just like it should and my task works when the assembly it is inspecting is in the same folder. I'd like to contribute this to the MSBuild community at tigris and have it in that source project if I can just figure this out. I'd rather not copy the inspected assembly into the NHibernate assembly .

Any tips would be helpful.

Is Monorail the WebForms killer?

I saw this quote in a forum today

<snip>In classic ASP.NET with MVP,...</snip>

We refer to asp before .net as 'classic' asp...so if we are now going to refer to asp.net as 'classic' does this mean the death of webforms?

One can only hope...

:)

Binsor Quack...er...Quick Tip

I thought this wasn't working before but tonight I needed to decorate/adapt a component in Windsor using Binsor . When I tried this before, I thought it bombed but I probably just didn't write it correctly..

So...for service IUnitOfWorkFactory I want to create an adapter that will be my default adapter throughout the app. Here's the Binsor bit:

 

#configure unit of work factories

Component("default_unit_of_work", IUnitOfWorkFactory, AppUnitOfWorkFactoryAdapter, inner: @nh_unit_of_work)

Component("nh_unit_of_work", IUnitOfWorkFactory, NHibernateUnitOfWorkFactory)

Note that per Windsor the first registered component is considered the 'default' when not resolved with a key. Boo lets me pass in the component by the key name using the syntax:

parameterName: @keyofregisteredcomponent

I am not sure if the INeedSecondPassRegistration interface  is what enabled this (I don't recall seeing it) but I am happy :)

OSS Reporting Tool?

Is it just me or does it seem like a huge gap in OSS for .NET not having a reporting tool...That may be something to look into...

Slideshow for script.aculo.us

Finally found a good slideshow that has cross fade effects with scriptaculous.

It's Here and is easy to wire up. Only snag I hit was if there is any whitespace in the <div> it is attaching your slides to, it will bomb. Be sure to keep whitespace OUT and it works a champ.

Also, the .slide-show class should be using position:absolute for crossfade to work. It 'snaps' into view otherwise. I just put a wrapper on the div it is talking to so that I could position it where I want by making it 'position:relative'.

Working With Monorail Contrib CodeGenerator

I have been tooling aorund with Elutian's CodeGenerator in the Contrib space of Castle's Monorail.

First, watch the screencast that explains how to set up the CodeGenerator. There is a typical Controller base class to use the generator provided. Basically, you need to just build the project from source and then configure your .csproj in your monorail/web project with the MSBuild target snippet provided. The 'SiteMap.generated.cs' will be, er, generated at build. One slight oddity I encountered is its interference with copying dependencies into my /web/bin folder during build. I'll probably just add a conditional to the build target or perhaps have it as part of a postbuild event to get around this and I am not familiar enough with MSBuild to work it out right now.

Once the generated file is in  your project you of course need to 'Include In Project' the .cs file. Now you can write syntax such as 'Site.Home.Index().Redirect()' instead of string literals in your controllers. One thing it will do, too, is provide the following syntax when working with areas:

  1. Assume area structure /admin/useradmin, where 'UserAdminController' sits in 'Controllers/Admin' .
  2. Next assume we have a controller called 'AdminController' sitting in the 'Controllers' folder of your project.
  3. Syntax for accessing the UserAdmin actions will be Site.AdminArea.UserAdmin.Actions.Index().Redirect(); >>note the 'AdminArea' node
  4. Syntax for accessing the Admin actions will be Site.AdminController.Actions.Index().Redirect(); // note the 'AdminController' node

One thing not supported (yet?) is the ability for the generator to reflect on any base classes to any inherited actions to the current controller. For example, if HenController:ChickenController and the definition for Index() is in ChickenController (which is abstract), the Index actions doesn't appear in the generated code for HenController. The workaround for this is to simply delegate the actions within HenController to the underlying action and the generator picks up on it. I've never worked in any kind of generation stuff so this might be something I'll poke around at patching if it isn't by design.

Another thing to keep in mind is naming collisions with any controllers called 'Services'. The generator uses the field _services internally in the generated file and so any usage of this as a Controller name caused name collisions. It would be better to have less-common names as internal fields for these kinds of things I think.

I couldn't get the strong-typed Flash/PropertyBag stuff going that is out there since they ported the very cool DictionaryAdapterFactory over to the components project. I had a hard time tracking with all the docs I could find that were written prior to the move of the DictionaryAdapterFactory and I am needing to move on...

I found an example Elutian posted that is helpful as well.

Overall, the generator is useful. I'd like to see something that automates breadcrumbs and the like as well so am thinking how to do that.

References

CSS Equal Column Height Using prototype.js and the Holy Grail

One of the difficulties with using the Holy Grail fluid layout is its usage of the PIE Method here. If you are going to do jump links you will be pulling your hair out.

So we are left with the common css layout quandry...do we use more complex css to get our floated columns equal heights or do we use javascript? The pragmatist in me says javascript. Maintainability is more important to me than the few users who aren't using javascript on my site.

I adapted this script from another I found (noted in code) to work with the prototype.js library. This also fixed an IE7 issue.

 

/*Adapted from http://www.thewatchmakerproject.com/journal/308/equal-height-boxes-with-javascript

fixing IE7 compatibility issues and using prototype.js loaded first*/

 

var CSSColumns = {

    maxHeight: 0,

    els: new Array(),

    equalise: function(){

        for (var i=0;i<arguments.length;i++) if (!$(arguments[i])) return;

        for(var i=0;i<arguments.length;i++)

        {

            this.els.push($(arguments[i]));

        }

        this.maxHeight = this.calcMaxHeight();

        for(var i=0;i<this.els.length;i++){

            this.els[i].style.height = this.maxHeight + "px";

        }

    },   

    calcMaxHeight: function(){

        var h = 0;

        for(var i=0;i<this.els.length;i++)

        {

            if(this.els[i].getHeight()>h)

            {

                h=this.els[i].getHeight();

            }

        }

        return h;

    }

}

 

So to attach it to my window.load event I can just use this

        <script type="text/javascript" src="${siteRoot}/Content/javascripts/csscolumns.js" ></script>

        <script type="text/javascript">           

            Event.observe(window, 'load', function() {

              CSSColumns.equalise('content','c1','c2','c3');

            });

        </script>

You simply pass in the element ids that you need to have height matching. Note that I am also passing a container element called 'content' that wraps my floated 'c1,c2,c3' divs. Otherwise, the divs will not be pushed all the way down.

 

It tested fine in FF, IE7, and Opera (who cares). Haven't fired it in IE6 but I'm sure it'll suck and I'm not sure I care about that :)

Monorail Design- Toggling layouts without maintaining multiple layout pages

As far as I can tell, Monorail is planning to support nested layouts (master pages) but doesn't currently do so.

In my current Monorail project I need to be able to support 1,2, and 3 column layouts in my #content section of my pages. I use css for layout and accessibility support so my markup remains the same in my layout with columns added or disappearing based on the css I hand it.

Since I can't use the 'CaptureFor' component within my layout pages, I needed to come up with some alternative way of passing the css that overrides my base layout css and keeps me from having to maintain multiple layout pages that are only differing by the <head/> content.

So first my <head/> inside 'default.brail':

 

    <head>

        <title>Company Name</title>

 

        <link href="${siteRoot}/Content/css/base.css" rel="stylesheet" type="text/css" />

        <!--implementor pages can inject styles here-->

        ${?styles}

 

        ${Ajax.InstallScripts()}

        ${Scriptaculous.InstallScripts()}

        ${ValidationHelper.InstallScripts()}

 

        <script type="text/javascript">

            <!--implementor pages can inject javascript here-->

            ${?javascripts}

        </script>

    </head>

Note the ${styles} parameter that I can use either from my views using the CaptureFor component, or as we'll see, in a Filter.

Now suppose I want to attach the LayoutAttribute to an action/controller. I can do Layout("default2column") and then let a Filter parse that attribute to handle the css injection:

 

            if(controller.LayoutName!=null)//ajax calls won't have a LayoutName
            {
                if (controller.LayoutName.ToUpper() == Settings.Default.LAYOUT_TWO_COLUMN.ToUpper())
                {
                    controller.PropertyBag["styles"] =
                        string.Format(Settings.Default.CSS_LINK, Settings.Default.LAYOUT_TWO_COLUMN);
                }
                controller.LayoutName = "default"; //don't pass layout name or else your ajax response will have it included...bad
            }
            return base.OnBeforeAction(context, controller);

First, I determine what layout name was assigned to the action ("default2Column"), then I can inject my desired css into the 'styles' view parameter. Finally, I switch the layout name to 'default' so that Monorail won't go looking for a layout called 'default2Column'. This allows me to have ONE default layout and use css to handle my layout...exactly what I want to do and beats managing multiple layouts.

BTW, I am using the 'Holy Grail' layout for 3 column, fluid content with minor modifications to deal with IE7 funniness.

If anyone is interested, I'll post the markup and css to show how to toggle between 3 and 2 column layouts with about 4 lines of css while keeping one layout to maintain.

After going through this it seems nested layouts wouldn't be the best solution to this after all. That's what I love about Monorail...there are a million simple ways of doing what you need without having to play the event-guessing-game as you do in WebForms. Plus, I keep the nitty-gritty view details out of my Controllers and isolate them in their own objects (ie, Filters). Sweet.

My First Monorail View Component : Image Box Out

On one of the projects I am working on we need to have an image with a caption on pretty much every page. Very common scenario. Now I can be sure all these types of regions in my site are consistent with css driving their layout.

So here is my ImageBoxOutComponent:

 

    public class ImageBoxOutComponent : ViewComponent
    {
        private string src = string.Empty;
        private string alt = string.Empty;
        private string css = "image-box-out";
        private string captionCss = "caption";

        public override void Initialize()
        {
            src = (String)ComponentParams["src"];
            alt = (String) ComponentParams["alt"];
            base.Initialize();
        }
        public override void Render()
        {
            StringBuilder output = new StringBuilder();
            output.AppendFormat("<div class=\"{0}\">", css)
                .AppendFormat("<img src=\"{0}\" alt=\"{1}\" />", src, alt)
                .AppendFormat("<p class=\"{0}\">", captionCss);

            RenderText(output.ToString());
            if(Context.HasSection("caption"))
            {
                Context.RenderSection("caption");
            }
            RenderText("</p></div>");
        }
        public override bool SupportsSection(string name)
        {
            return name == "caption";
        }
    }

The accompanying CSS is simply:

/*.image-box-out*/

.image-box-out

{

    max-width:260px;

    background:#333;

    overflow:hidden;

}

The 'overflow' simply hides the portion of the image that might exceed the wrapper div.

 

Now to use it in a View I simply do this:

<?brail component CaptureFor, {"id":"imageboxout"}:?>  

   <?brail component ImageBoxOut, {"src":"${siteRoot}/Content/images/300x300.png","alt":"alttexthere!"}:

        section caption:?>

            FANCY CAPTION

        <?brail end ?>

    <?brail end ?>       

<?brail end ?> 

Monorail View Component Quicky : Accessing ${siteRoot}

Need to access ${siteRoot} from a ViewComponent?

Use base.RailsContext.ApplicationPath

Building Castle, Rhino Commons, and ViewComponents

 

Since I came across a versioning conflict with NHibernate in my current Monorail project between 1.2.0 and 2.0 I needed to build the Castle trunk. Basically this was hanging the ARDataBinding in my controller.

 Here's what I did and while it worked, it's a pain in the butt:

1) Update Oren's RhinoCommons from trunk

2) Update Castle from trunk.

2a) Resolve Monorail-VS2005.csproj conflicts, accepting NHib 2.0 version (A); Accept as resolved

3) Get the latest Monorail.ViewComponents (from Contrib)

4) Build RhinoCommons

5) Throw the assemblies from that project into the Castle/SharedLibs

6) Fix problems I had with BrailJSGenerator (for some reason it wasn'tpulling the recent IJsGenerator param changes in from the trunk...)

7) Update NHibernateIntegration Facility and ActiveRecordIntegration Facility to implement (delegate) the NHibernate ISession methods SetBatchSize and CreateMultiCriteria

8) Build Castle

9) Throw resulting binaries in Monorail.ViewComponents and build that

10) Place all this in my own project and build

ARDataBind is in business with no versioning conflicts now. ALL WORKS.

Am I making this WAY too hard or am I missing something? I think the trunk is running on me, not the other way around ...

Only about an hour and a half, but I want to code not configure all night :)

UPDATE: Check out Oren's secret formula for building Castle/NHib/Rhino ...