Not using Linq to it’s fullest can produce the worst of both worlds

I’m parsing some XML and need to do one thing if there are a group of XML elements with the same name and another thing if just one element with a given name.

Here my first attempt, yuck!

XElement on = null;
foreach (XElement element in elements.OrderBy(x => x.Name.LocalName))
{</p>



var current = element;
<span class="kwrd">if</span> (elements.Count(x => current.Name.LocalName.Equals(x.Name.LocalName)) > 1)
{
    <span class="kwrd">if</span> (on == <span class="kwrd">null</span> || !current.Name.LocalName.Equals(on.Name.LocalName))
    {
        <span class="kwrd">yield</span> <span class="kwrd">return</span> <span class="kwrd">new</span> JProperty(current.Name.LocalName,
                                   <span class="kwrd">new</span> JArray(
                                    elements.Where(x => current.Name.LocalName.Equals(x.Name.LocalName)).Select(
                                        x => <span class="kwrd">new</span> JValue(x.Value))));
        on = current;
    }
}
<span class="kwrd">else</span>
{
    <span class="kwrd">yield</span> <span class="kwrd">return</span> FromElement(element);
}

}

That's really bad, Linq is probably making the code worse. After some refactoring...

foreach (var group in from e in elements group e by e.Name.LocalName)
    if (group.Count() > 1)
        yield return new JProperty(group.First().Name.LocalName,
            new JArray(from x in @group select new JValue(x.Value)));
    else
        yield return FromElement(group.First());

The code here is easier to read shorter and clearer. Much better.


What’s Needed for Castle Validation To Work

Make sure the view knows what to validate

The object or object type to be validated must be sent to the view.

PropertyBag["signuptype"] = typeof(SignupInfo);
// or
PropertyBag["signup"] = new SignupInfo;

Remember to use Flash if redirecting, like in the case of a validation error on the server side.

Make sure the JS files are included

Either just include the files with a script tags:

<script type="text/javascript" src="${siteroot}/Content/js/prototype.js"></script>
<script type="text/javascript" src="${siteroot}/Content/js/scriptaculous.js"></script>
<script type="text/javascript" src="${siteroot}/Content/js/formhelper.js"></script>
<script type="text/javascript" src="${siteroot}/Content/js/behaviour.js"></script>

Or using the InstallScripts method of the respective helpers. With the brail view engine it would be:

${Ajax.InstallScripts()}        
${Scriptaculous.InstallScripts()}        
${FormHelper.InstallScripts()}

Make sure to use the FormHelper

Make sure you use the FormHelper for at least the start and end form tags, but it should be used for the fields too if you want the values auto populated on an exception.

${Form.FormTag({@area:'', @controller:'WaitingList', @action:'AddToList', @immediate:'true', @useLabels:'true'})}
<?brail OutputSubView('/shared/errorsummary') ?>
<div class="formrow">
${Form.LabelFor("signup.Name", "Name:")}
${Form.TextField("signup.Name", {@style: 'width: 300px;'})} <br/>
</div>
<div class="formrow">
${Form.LabelFor("signup.Email", "Email Address:")}
${Form.TextField("signup.Email", {@style: 'width: 300px;'})} <br/>
</div>
<div class="formrow">
${Form.Submit("Add Me")}
</div>
${Form.EndFormTag()}

The immediate and useLabels are optional arguments for the validation JS.

Make sure your controller class inherits  SmartDispatchController

This will already be the case most of the time, but SmartDispatchController knows to validate the bound objects.

public class WaitingListController : SmartDispatcherController

Make sure you have validation attributes on your Model

There are a lot of build in validation attributes and a way to add custom attributes. There is also a way to bind the validation to a model without attributes, but I’m not going to cover that here.

public class EmailInfo
{
    [ValidateNonEmpty]
    public string Name { get; set; }

    [ValidateNonEmpty, ValidateEmail]
    public string Email { get; set; }
}

The Validation Attributes are in the Castle.Components.Validator namespace.

Make sure you check validation on your Action

You will most likely already have a DataBind attribute on your model parameter, but you will need to add Validate = true. Within you action, check if you have validation errors and redirect to the form if you do. Be sure to Flash the model instance and the error summary. This is important as the client might have disabled javascript and because some validators are server side only.

public void AddToList([DataBind("signup", Validate=true)] EmailInfo emailInfo)
{
    if (HasValidationError(emailInfo))
    {
        Flash["signup"] = emailInfo;
        Flash["summary"] = GetErrorSummary(emailInfo);
        RedirectToAction("index");
        return;
    }

    EmailAddress address = new EmailAddress(emailInfo.Name, emailInfo.Email);
    _waitingListRepository.Put(address);

    WaitingListAdminController.WAITING_LIST_KEY);
    Redirect("waitinglist", "onlist");
}

Unit Testing

Unit testing is obviously not required for this to work. If you are testing and using the TestSupport classes with BaseControllerTest you will need to add the following before calling your action to test an invalid model instance. There may be a better way to test this, but here’s what I did.

[Test]
public void Add_To_List_Expect_Validate_Fail_Redirect()
{
    EmailInfo info = new EmailInfo();

    if (!_controller.Validator.IsValid(info))
        _controller.PopulateValidatorErrorSummary(info, _controller.Validator.GetErrorSummary(info));
                
    _controller.AddToList(info);
        
    Assert.That(Response.WasRedirected);
    Assert.That(Response.RedirectedTo, Is.EqualTo("/Controller/index.castle"));
}

There’s a lot covered here, but really it’s not much more code then what you’d have without validation and you get a robust validation framework with both client and server side validation.


Getting dasBlog and Castle.MonoRail to work together

Ok, it’s not really about getting dasBlog to work with MonoRail, but really remembering that web.config has a cascading effect on sub applications in IIS. I had two bugs today the first of which took a long time to find, but both related to the root web.config having entries that caused problems in the sub application (dasBlog in this case).

The first issue, for some reason I had the domain attribute in the forms authentication section set to / in the root web.config. Not sure why it was set like that, but apparently MonoRail overrides the domain value when setting cookies, while dasBlog doesn’t. This has the effect of not being able to log in to dasBlog, but not producing any errors, and in fact it says the login was a success. However, no cookie is issued. Removing the domain attribute fixed this problem.

The second issue was regarding httpModules, in this case MonoRail’s routing module. This caused problems by requiring Castle dll’s be copied to the blogs bin directory, but more importantly it caused the FreeTextBox control to break and the blogging.aspx page to break because in these cases the files didn’t exists on disk and so (I think) the routing engine kicked in, though not setup on this application and missing dependencies, it failed. The fix for this, also easy and strait forward, is to remove the routing module from the blog application. To do that, you can just add a remove tag to the httpModules config like:

<httpModules>
  <remove name="routingEx"/></httpModules>

Both issues were simple enough, but not very obvious at the time.


CloudSH.com is in Alpha!

CloudSH.com went into alpha last night, read more about it here.


Thoughts about 3rd party libraries and a projects build

One thing I’m going start doing when starting a new project is to initially create a directory for compiled 3rd party libraries in the new projects root. Maybe one for debug builds and one for release builds. Doing this will save a lot of time later, one is always created later in the projects lifecycle, but then it requires resetting all the references in the build system and the project files. This is important for building the project on a different box anyway (like for continuous integration). I think this gets really important when working off an OSS projects trunk source code so the working build always has the correct OSS build.


My Startup Life [Review]

51W7RJzp3YL._SL160_

I just finished reading My Startup Life by Ben Casnocha. It an interesting and enjoyable read. It’s a mix of his story and insights and learnings from along the way. The insights and learnings are in side bars, which I found distracting. I might have enjoyed the story first and then then insights second. But I think a little more detail in the story and less or no sidebars would have been better. Anyway, I’d recommend it for anyone with an entrepreneurial streak. I’d give it 3/5 for a great story, good content and an okay mixing of the two.


Prototype classes and bind

I’m working with the Prototype JS library classes, which I’m really liking. But I ran into one stumbling block, Binding. In JS the scope in which your function can be called can change and as such the ‘this’ object can change. The main places this can happen is call back functions for events or anytime anonymous methods are used. Justin Palmer explains it really well here.

$(‘console’).observe(‘click’, prompt.focusLine.bindAsEventListener(prompt));

The above will bind the focusLine method to the _prompt object when the event callback is fired. The same thing applies for events within a custom defined Class.


Brutalist Framework