When Decoupling Goes Bad

I’m currently reading ASP.Net MVC 2 in Action and overall, the books seems solid. I can say this because I’ve read about 20 pages and agree with most of it. However, the 20 pages I’ve read do contain some advice that seems overdone at best and downright confusing to future developers at worst. The chapter I’m reading is Data Access with NHibernate. I’m working on an application that contains an ASP.Net web site backed by a PostgreSQL database. Previously, all my applications used MSSQL and therefore were set up using Linq-to-SQL as a poor man’s ORM. With PostgreSQL, that’s no longer an option so I’m in the process of learning NHibernate and Fluent NHibernate, a task that’s long overdue.

I hate learning a new technology by doing everything wrong the first time so I went looking for some best practices or architecture suggestions for setting up NHibernate. This book had an entire chapter on that and so I dove right in. Overall, it’s been very useful. Heavy use of Dependency Injection and Inversion of Control nicely decouple the pieces of the app from each other. However, the authors recommend something that seems a little extreme to me.

The example solution has a UI project which is the ASP.Net site, a Core project containing domain models and code, an Infrastructure project for things like data access and assorted test projects including an Integration Test project. The authors point out that the only project that references the Infrastructure project is the Integration Test project. Their rationale for this is that Infrastructure is necessarily fluid. Because of this, you don’t want to couple the core or UI to it. They set this up by using runtime DI to inject dependencies from the Infrastructure project into UI components. Specifically, the data access repositories that certain controllers need are discovered at runtime using settings in the web.config. They claim that this results in a completely decoupled application.

However, in order for this to work, the UI project needs to have access to the Infrastructure assemblies and config files. Normally, this would happen via an explicit reference in Visual Studio which would result in the necessary files being copied into the UI project at compile time. Because the UI project doesn’t have that reference, the authors have to get the files there another way. Their solution is to use a post build step in the Infrastructure project to copy the necessary files. To me, this only serves to make the reference implicit, something is likely to cause issues down the road.

The UI definitely has a dependency on the Infrastructure project. It seems extreme to hide that dependency in a post build step instead of showing it explicitly in the project references of the website. It’s one thing to write decoupled code that is easy to test and change. It’s entirely another to force developers to jump through hoops and keep track of idiosyncrasies like implicit project references. However, being a complete newbie to this form of architecture, maybe I’m missing something. Is there a true reason for managing dependencies between projects in this manner? If so, why not manage all of them in the same manner, do everything at runtime and copy all files via post build steps? I think the answer is that there isn’t a real reason for this except for the purity of the architecture, something that should immediately be questioned for intrinsic use. I’d love to hear any opinions from the experts out there.

Making CheckBoxList Play Nice With JavaScript

I’m working on a web page that allows the user to apply a variety of filters to a set of data. The old implementation involved a check box for each filter and then a ListBox with MultipleSelection set to true. The user would tick what ever filter they wanted to include and then select the items out of the ListBox. Every time the user makes a selection in one of the ListBoxes, we’re making an AJAX call to update the current filters. That works great but the user has to do two things, first tell us that they want to use a particular filter using the appropriate CheckBox and then select items out of the ListBox, sometimes holding down the Shift or Control key to do multiple selection.

We decided to change that to a CheckBoxList for each filter. This removes one step and makes the UI a little more fluid. However, it did cause one problem. Previously, the ListBoxes were being loaded with data on PageLoad by just adding a new ListItem for each piece of data. This works well because the ListItem can hold whatever value you want to key off of. However, a CheckBoxList renders as a table of CheckBoxes, none of which have the ability to hold a piece of data to key off of.

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            for(int x = 0; x < 3; x++)
            {
                MyListBox.Items.Add(new ListItem("my value is " + x, x.ToString()));
            }
        }
    }

That code rendered a ListBox that had source like this:

                

From there, it was really easy to grab the value of any selections via JavaScript. Unfortunately, as mentioned above, the CheckBoxList does not render that way. Using the same code in the PageLoad ends up rendering this HTML:

                

As you can see, none of the checkboxes have the value attribute. There is now a label for each one but it has the Key of the ListItem and not the Value which isn't particularly helpful when you want to display one piece of data for the user but process another one based on their selection. What to do?

As it turns out, you can add an attribute that gets rendered as a span around both the input and label elements. In JavaScript, you can then grab an array of the inputs and an array of the span elements. When one of the input boxes is found to be checked, you can get the corresponding span element's attribute and use it. It looks a little something like this:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            for(int x = 0; x < 3; x++)
            {
                ListItem li = new ListItem {Text = "my value is " + x, Value = x.ToString()};
                li.Attributes.Add("myspecialid", x.ToString());
                MyCheckBoxList.Items.Add(li);
            }
        }
    }

When the items are loaded into the ListItems, we add an attribute called "myspecialid". It can be anything you want though it doesn't work if you pick a known attribute like id or value. Once that's done, the HTML renders like this:

                

Our new attribute has been included in a span tag around the input element and the value we want to track is included there. Now in JavaScript, we can do this:

function DoSomething() {
    var tableBody = document.getElementById("Tabstrip1_StudentsTab_MyCheckBoxList");
    var inputArray = tableBody.getElementsByTagName("input");
    var spanArray = tableBody.getElementsByTagName("span");
    for (var x = 0; x < inputArray.length; x++) {
        if (inputArray[x].checked) {
            alert("The id I want is " + spanArray[x].getAttribute("myspecialid"));
        }
    }
    if (groupsSelected.length > 0) {
        __aspx.HandleMonitorGroupFilter(groupsSelected);
    }
}

We grab all the input and span elements in the table. Then when we find a checkbox that is checked, we can grab the attribute we're interested in off of the appropriate span element using the getAttribute method. This is slightly hackish in that the two arrays of elements have to be in the same order but that seems like a reasonably safe assumption to make.

Overall, it seems like a good way to make the UI more fluid while still retaining the ability to manipulate necessary data on the AJAX calls.