Monorail: Exception Handlers: Flash and Redirect

e setting up exception chaining on monorail, I wanted to use the Flash properties to store the LastException for next request, an error page. This by default doesn't work if the exception happens outside of the Castle.MonoRail.Framework.MonoRailHttpHandler.Process method. This is because the Flash variables don't get saved until after this method. One note here, the Process method is wrapped in a try, finally block and the Flash properties will be saved in the case of an exception on the Process method, some additional checking in the exception handler may be needed to catch this. Anyway, I added the following line to my last handler and the Flash properties are working great.<br /><br /><span style="font-family: Courier New;">context.Session[Flash.FlashKey] = context.Flash;</span><br /><br /> Secondly, I wanted to redirect to different views based on the exception, which I wasn't able to do. The reason was that the asp.net framework noticed the exception an handled according, not what I wanted. The way around this is to clear the error using the Server.ClearError() method before redirecting.<br /><br /><span style="font-family: Courier New;">context.UnderlyingContext.Server.ClearError();</span><br /><div style="clear: both; padding-bottom: 0.25em;"></div>

Using nant and tallow to create usable WIX component.

    <p>Creating installer for web application can be a pain, but using tallow and an nant script element can make things a lot easier.</p>
    <p>Once my nant script was building my solution and web project with all the needed output files I begin to setup automating the build of the WIX component for the web application.</p>
    <p>As you know tallow output is not usable as is, some custom handling needs to be done. I've found the script element of nant to work well for this. I've also created a new class library project to keep the script block small, and keep the source in a project. I've included the class library in the solution build. </p>
    <p>Nant target:</p>
    <!-- code formatted by http://manoli.net/csharpformat/ -->
    <pre class="csharpcode">&lt;property name="wix.websitefragment.file" value="${build.output.temp}\website-fragment.wsx"/&gt;<br />&lt;target name="buildwebsitewsx" depends="solution"&gt;<br />    &lt;mkdir dir="${build.output.temp}"/&gt;<br />    &lt;exec program="${wix.bin}\tallow.exe" workingdir="${build.output.temp}" output="${wix.websitefragment.file}"&gt;<br />        &lt;arg value="-d &amp;quot;${compile.output.webapplication}&amp;quot;"/&gt;<br />        &lt;arg value="-nologo"/&gt;<br />    &lt;/exec&gt;<br />    &lt;script language="C#" verbose="true"&gt;<br />        &lt;references&gt;<br />            &lt;include name="${compile.output}\InstallHelper.dll"/&gt;<br />        &lt;/references&gt;<br />        &lt;imports&gt;<br />            &lt;import namespace="InstallHelper"/&gt;<br />        &lt;/imports&gt;<br />        &lt;code&gt;<br />        &lt;![CDATA[<br />        public static void ScriptMain(Project project) {<br />            string file = project.Properties["wix.websitefragment.file"];<br />            new FixTallow(file, "My.ComponentGroup.Name").UpdateFile();<br />        }<br />        ]]&gt;<br />        &lt;/code&gt;<br />    &lt;/script&gt;<br />&lt;/target&gt;<span class="kwrd"></span></pre>
    This calls the tallow application on the directory where the web application is built. Then loads and calls the InstallHelper.dll to modify the tallow output into something more usable. <br /><p>The FixTallow class loads the tallow output into an XML document and takes the following actions; adds a component group, creates guids for the components, renames the directory id's and changes the directoryRef element to point to the INSTALLDIR.</p><p>The component group needs to be created so a reference can be added to the main WIX file. This is because tallow creates a component for each directory (or each file) and because I don't want to update the main WIX file every time there is a directory added or removed from the web application. The group name is passed the the constructor of the FixTallow class. </p><p>FixTallow also renames the directory id's so that I can reference them if needed from the main WIX file, however if the directory is removed or renamed, the main WIX file will need to be updated. Also, the root DirectoryRef element is changed to reference INSTALLDIR which needs to be set in the main WIX file. This is a good idea as it allows the installation directory to be changed when installing.</p><p>FixTallow.cs</p><pre class="csharpcode"><span class="kwrd">    public</span><span class="kwrd">class</span> FixTallow<br />    {<br /><span class="kwrd">  private</span><span class="kwrd">readonly</span><span class="kwrd">string</span> _filename;<br /><span class="kwrd">    private</span><span class="kwrd">readonly</span><span class="kwrd">string</span> _componentGroupName;<br />        XmlDocument _document = <span class="kwrd">new</span> XmlDocument();<br />        XmlNamespaceManager _manager;<br />        XmlElement _compGroup;<br /><br /><span class="kwrd">   public</span> FixTallow(<span class="kwrd">string</span> filename, <span class="kwrd">string</span> componentGroupName)<br />        {<br />            _filename = filename;<br />            _componentGroupName = componentGroupName;<br /><br />            _manager = <span class="kwrd">new</span> XmlNamespaceManager(_document.NameTable);<br />            _manager.AddNamespace(<span class="kwrd">string</span>.Empty, <span class="str">"http://schemas.microsoft.com/wix/2003/01/wi"</span>);<br />            _manager.AddNamespace(<span class="str">"ns"</span>, <span class="str">"http://schemas.microsoft.com/wix/2003/01/wi"</span>);<br />        }<br /><br /><span class="kwrd"> public</span> FixTallow UpdateFile()<br />        {<br />            _document.Load(_filename);<br /><br />            AppendComponentGroupElement();<br /><br /><span class="kwrd">        foreach</span> (XmlElement element <span class="kwrd">in</span> _document.SelectNodes(<span class="str">"//ns:Component"</span>, _manager))<br />            {<br />                element.Attributes[<span class="str">"Guid"</span>].Value = Guid.NewGuid().ToString().ToUpper();<br />                AppendComponentToGroup(element.Attributes[<span class="str">"Id"</span>].Value);<br />            }<br /><br />            ChangeDirectoryRefId();<br /><br />            UpdateDirectoryIds();<br /><br />            _document.Save(_filename);<br /><br /><span class="kwrd">      return</span><span class="kwrd">this</span>;<br />        }<br /><br /><span class="kwrd">        private</span><span class="kwrd">void</span> UpdateDirectoryIds()<br />        {<br /><span class="kwrd">            foreach</span> (XmlElement directory <span class="kwrd">in</span> _document.SelectNodes(<span class="str">"//ns:Directory"</span>, _manager))<br />            {<br /><span class="kwrd">                string</span> directoryName = (directory.Attributes[<span class="str">"LongName"</span>] == <span class="kwrd">null</span>)<br />                                           ?<br />                                       directory.Attributes[<span class="str">"Name"</span>].Value<br />                                           :<br />                                       directory.Attributes[<span class="str">"LongName"</span>].Value;<br />                directory.Attributes[<span class="str">"Id"</span>].Value = directoryName + <span class="str">".Dir"</span>;<br />            }<br />        }<br /><br /><span class="kwrd">        private</span><span class="kwrd">void</span> ChangeDirectoryRefId()<br />        {<br />            _document.SelectSingleNode(<span class="str">"/ns:Wix/ns:Fragment/ns:DirectoryRef/@Id"</span>, _manager).Value = <span class="str">"INSTALLDIR"</span>;<br />        }<br /><br /><span class="kwrd">        private</span><span class="kwrd">void</span> AppendComponentToGroup(<span class="kwrd">string</span> componentId)<br />        {<br />            XmlElement componentRef = _document.CreateElement(<span class="str">"ComponentRef"</span>, _manager.DefaultNamespace);<br />            XmlAttribute componentRefId = _document.CreateAttribute(<span class="str">"Id"</span>);<br />            componentRefId.Value = componentId;<br />            componentRef.Attributes.Append(componentRefId);<br />            _compGroup.AppendChild(componentRef);<br />        }<br /><br /><span class="kwrd">        private</span><span class="kwrd">void</span> AppendComponentGroupElement()<br />        {<br />            _compGroup = _document.CreateElement(<span class="str">"ComponentGroup"</span>, _manager.DefaultNamespace);<br />            XmlAttribute compGroupId = _document.CreateAttribute(<span class="str">"Id"</span>);<br />            compGroupId.Value = _componentGroupName;<br />            _compGroup.Attributes.Append(compGroupId);<br />            _document.SelectSingleNode(<span class="str">"/ns:Wix/ns:Fragment"</span>, _manager).AppendChild(_compGroup);<br />        }<br />    }</pre><p>The main WIX file needs to include a few things for this to work. First, it much have a diretory element with INSTALLDIR as it's Id. Second, a ComponentGroupRef element pointing the component group name specified in the FixTallow constructor needs to be included in the Feature element.</p><pre class="csharpcode">...<br /><span class="kwrd">&lt;</span><span class="html">Directory</span><span class="attr">Id</span><span class="kwrd">="TARGETDIR"</span><span class="attr">Name</span><span class="kwrd">="SourceDir"</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;</span><span class="html">Directory</span><span class="attr">Id</span><span class="kwrd">="ProgramFilesFolder"</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;</span><span class="html">Directory</span><span class="attr">Id</span><span class="kwrd">="INSTALLDIR"</span><span class="attr">Name</span><span class="kwrd">="myapp"</span><span class="attr">LongName</span><span class="kwrd">="MyApplicationName"</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;/</span><span class="html">Directory</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;/</span><span class="html">Directory</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;/</span><span class="html">Directory</span><span class="kwrd">&gt;</span><br />...<br /><span class="kwrd">&lt;</span><span class="html">Feature</span><span class="attr">Id</span><span class="kwrd">="Complete"</span><span class="attr">Level</span><span class="kwrd">="1"</span><span class="kwrd">&gt;</span><br /><span class="kwrd">&lt;</span><span class="html">ComponentGroupRef</span><span class="attr">Id</span><span class="kwrd">="My.ComponentGroup.Name"</span><span class="kwrd">/&gt;</span><br /><span class="kwrd">&lt;/</span><span class="html">Feature</span><span class="kwrd">&gt;</span><br />...</pre>Lastly, the tallow output needs to be passed to the candle and light applications when building the msi file with something like this:<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">exec</span><br /><span class="attr">program</span><span class="kwrd">="${wix.bin}\candle.exe"</span><br /><span class="attr">workingdir</span><span class="kwrd">="${build.output.install}"</span><br /><span class="attr">commandline</span><span class="kwrd">="Main.wsx website-fragment.wsx"</span><span class="kwrd">/&gt;</span><br />...<br /><span class="kwrd">&lt;</span><span class="html">exec</span><br /><span class="attr">program</span><span class="kwrd">="${wix.bin}\light.exe"</span><br /><span class="attr">workingdir</span><span class="kwrd">="${build.output.install}"</span><br /><span class="attr">commandline</span><span class="kwrd">="-out MyApplication.msi Main.wixobj website-fragment.wixobj"</span><span class="kwrd">/&gt;</span></pre><span class="kwrd">There was a lot of setup here, but once completed changes can be made to the web application without modifying the WIX files, resulting in an up to date MSI on each build.</span><br /><div style="clear: both; padding-bottom: 0.25em;"></div>

Adding wix support for VS.NET

 the .xsd files in the wix\doc directory to C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas directory.<div style="clear: both; padding-bottom: 0.25em;"></div>

Validate if checkbox is checked using really easy validation

/ Needs Really easy validation.js script & prototype.js /

function validateIfChecked(v, e) {
var cbId = e.getAttribute(‘usecheckbox’);
if (cbId != ‘undefined’) {
if ($(cbId).checked) {
var validationType = getValidationType(e);
return !Validation.get(‘IsEmpty’).test(v) && Validation.get(validationType).test(v)
}
else {
$(e).value = ‘’;
return true;
}
}
return true;
}

function getValidationType(e) {
var classes = e.className.split(‘ ’);
for (i = 0; i < classes.length; i++) {
if (classes[i].indexOf(‘validate-checkbox-’ >= 0))
return classes[i].replace(‘validate-checkbox-’, ‘’);
}
return ‘validate-number’; // default;
}

Validation.add(‘validate-checkbox-required’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-number’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-digits’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-alpha’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-alphanum’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-date’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-email’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-url’, ‘Please provide a valid value when checked’, validateIfChecked);
Validation.add(‘validate-checkbox-validate-currency-dollar’, ‘Please provide a valid value when checked’, validateIfChecked);

Realy Easy Validation


Nhibernate Generics Lazy Loaded Collections

Child objects not saved when added to a lazy loaded collection that is not initialized. See this post for more info.


JavaScript Prototype notes

Prototype adds to the array class, amoung other things, which can break other javascript files, like fValidate.

prototypify – running prototype code with legacy code – provides a work around and more explaination.

really easy field validation with prototype – is a validation script based on prototype.


Ajax javascript issues.

Javascript functions injected into the DOM using innerHTML will not work. So using something like:
<br />mydiv.innerHTML = [html result from ajax method call];<br />&hellip;<br /><div id=&ldquo;mydiv&rdquo;><br /></div><br />
make sure the [html result from ajax method call] doesn’t contain javascript, other then events (onclick, onblur, etc.).


Brutalist Framework