Data Binding CascadingDropDownList

The CascadingDropDownList (CDDL) is a very handy control – I have used it in a couple of different situations.  I recently ran into an interesting implementation of using it.

Consider the basic CDDL that is used as an example on the AJAX homepage (http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/CascadingDropDown.aspx)

I duplicated the project and added a twist – the values in the CDDLs are bound to another class.  I called this class CarOrder.  This CarOrder class has the following interface/implementation:

    public class CarOrder

    {

        public int MakeId { get; set; }

        public int ModelId { get; set; }

        public int ColorId { get; set; }

    }

Instanceses of CarOrders are served by a Factory class like so:

        public CarOrder GetCarOrder()

        {

            CarOrder carOrder = new CarOrder();

            carOrder.ColorId = 0;

            carOrder.MakeId = 0;

            carOrder.ModelId = 0;

 

            return carOrder;

        }

 

        public void UpdateCarOrder(CarOrder carOrder)

        {

 

        }

The actual implementation of the factory is not germane for this blog so I left it out.  Once I get better at Mocking, I can provide a more detailed example.

I then added a Default page to my project and constructed it as so:

 

  The FormView’s Update Panel looks like so:

                <asp:DropDownList ID="DropDownListMake" runat="server" Height="16px"

                    Width="211px" SelectedValue=’<%# Bind("MakeId") %>

                    DataSourceID="ObjectDataSourceCarOrder" DataTextField="MakeId"

                    DataValueField="MakeId">

                </asp:DropDownList>

                <cc1:CascadingDropDown ID="DropDownListMake_CascadingDropDown" runat="server"

                    Category="Make" Enabled="True" PromptText="Select Make"

                    ServiceMethod="GetMakes" TargetControlID="DropDownListMake"

                    UseContextKey="True">

                </cc1:CascadingDropDown>

Note that the data binding is with the DropDownList.  When I run the page, I get the following error:

‘DropDownListMake’ has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value

So Then I put the SelectedValue to the CascadingDropDown like so:

                <asp:DropDownList ID="DropDownListMake" runat="server" Height="16px"

                    Width="211px">

                </asp:DropDownList>

                <cc1:CascadingDropDown ID="DropDownListMake_CascadingDropDown" runat="server"

                    Category="Make" Enabled="True" PromptText="Select Make"

                    ServiceMethod="GetMakes" TargetControlID="DropDownListMake"

                    SelectedValue=’<%# Bind("MakeId") %>  UseContextKey="True">

                </cc1:CascadingDropDown>

And things ran like a champ

 

Some things to remember:

  • Disable EventValidation On the page (or master page if you are using one)
  • If you are using a method from the code-behind, make sure your script manager has EnablePageMethod set to true
  • Make sure your method matches the definition AND
  • If it is a code-behind, make sure the method is marked as static and you use both of these attributes:

[WebMethod]

[ScriptMethod]

Exam Time

I did not post this week – I haven’t done any new programming at all – I have been studying for my exam.  See you next week.

Martin redux

Speaking of Martin, I put together a list of highlights from his book Clean Code.

Following Kent’s 4 Rules of Design

1.       Run all of the tests

2.       Contain no duplication

3.       Express the intent of the programmer

4.       Minimize the number of classes and methods

(interestingly, #3 and #4 are often at odds.  As Martin says “ High class and method counts are sometimes the result of pointless dogmatism” (page 176)).

Writing code is an iterative process.  There are several catch-phrases you can use to reinforce that point:

1.       You need to write dirty code to get clean code

2.       Red light/green light/refactor

3.       Make it work, then make it right

4.       Refactor often, even working code

The reason it is iterative is because you will not get it right the 1st time and you need to keep refactoring to move towards the single responsibility principle, etc… 

Readable code is a must – because the average developer spends 10 times as much time reading his/her own code when writing a new line.  I am sure that number is higher when it is someone else’s code (or their own code 1 year later).  Now I see why everyone wants to work on new projects – less code to read.

Code should be so readable that you don’t need comments.  It is not ok to write a good comment to explain bad code – fix the code!

Finally, in his Smells and Heuristics section, I found many of the things that I have done that kicked off a spidy-sense warning but until now, I have realized why:

·         Obsolete Comments

·         Commented Out Code

·         Too Many Arguments

·         Dead Function/Code

·         Prefer Polymorphism to If/Else or Switch/Case

·         Functions Should Do 1 Thing

·         Functions Should Descend Only 1 Level Of Abstraction

 

Clean Code and Unit Testing

I am studying hard for my 70-568 exam at the end of the month so I have not dived deeper into development.  I did read Martin’s Clean Code over the last week and I found myself nodding in agreement more often than not.   I’ll never look at code comments the same way again.

 

I also started The Art of Unit Testing by Osherove.  I assumed that there were different levels of Unit Testing – good enough, good, and great.  However, Osherove doesn’t define it like that – he maintains that Unit Testing is a progression to Stubbing and Mocking.  If so, you need to refactor all of your code to include Interfaces and Dependency Injection and then use a Mocking Framework.  In short, there is no way to Unit Test an existing project that wasn’t set up for Testing in the 1st place. 

 

I think this is where dogma meets progma (my word, use it at your peril)  – I know many projects that would benefit from basic testing (Unit, Regression, Integration or a combo/bastardization of all three) but to refactor the code to support IoC and Mocking is not viable.  I know that Unit Testing is still in its infancy so I wonder if additional patterns will develop to support testing that defies traditional definitions.

Code Access Security Analogy

I am a big fan of using analogies to make a complex topic more accessible.  I was working though Microsoft .NET Framework Application Development Foundation by Tony Northrup when I came on a great analogy in his chapter on Code Access Security.  He used an example of a party that you are hosting (your method), a bouncer you have hired (.NET Framework Runtime),  4 guests you have invited (calling assemblies), and the invitation(s) you printed (the CAS permission of choice).  I had an a-ha moment with LinkedDemand and Demand.  I don’t use CAS on a day-to-day basis so I am not as familiar with the API – this will be a focus of my studies for my next exam (70-568 at the end of this month).

On another topic, I am reading The Pragmatic Programmer for light reading.  I think it is a great book.  I may not agree with some of their sections about coding, but their sections about personal development and programming ethos is spot on.

LINQ: Many paths to the same end

One of the real draws to using LINQ is that it affords many solutions to a single problem.  This can be good when finding the most performant code, and this flexibility helped me around an error with another API.

I have a Entity Framework data model of a swim team with 1 Gender and 1 Family having many swimmers and 1 swimmer being a part of many seasons.  Entity framework has some pluses (what with that cool designer, a unified model for all data sources, etc…) but what it does not do well is respond to change.  In this case, GenderId and FamilyId started as scaler properties of the Swimmer Class but then I changed them into association properties on the server using foreign keys.  Updating the model via the designer worked well enough (though you do need to remove the properties of any field you drop by hand) but the problem came in the LINQ.

I wanted to query all swimmers who were in a certain season.  I wrote the query like so: 

            var query = (from ss in CurrentContext.tblSwimmerSeasons

                         .Include("tblSwimmers")

                         .Include("tblSwimmers.tblGenders")

                         .Include("tblSwimmers.tblFamily")

                         where ss.tblSeason.SeasonID == 1

                         select ss.tblSwimmer);

Notice that I am using eager loading on the lookup tables.  The problem was that tblGenders and tblFamily come back null every time for every record.  Since I have done this exact query before, my guess is that the designer somehow is screwing up the SQL that it is generating because of the changes I made.   

The first way out of the problem is to use lazy loading like this: 

            foreach (var item in query)

            {

                item.tblFamilyReference.Load();

                item.tblGenderReference.Load();

                //etc…

            }

However, the performance problems with the multiple server round-trips makes this an unrealistic solution with a data set of any size. My next though was to use Entity-SQL but I really don’t want to mix languages in my solution for the sake of consistency.  I then realized that the select statement was forcing the data load in the Select in the SQL being generated so all I had to do was be explicit in the tables I wanted:

            var query = (from ss in CurrentContext.tblSwimmerSeasons

                         where ss.tblSeason.SeasonID == currentSeason

                         select new { ss.tblSwimmer, ss.tblSwimmer.tblGender,

                         ss.tblSwimmer.tblFamily });

 

worked like a charm.

After reading up a bit, my understanding is that the new Entity Designer in 4.0 will be more capable with changes – let’s hope so.

Where to place the code?

I had a theoretical discussion with a development team lead yesterday that had some practical implications.  He has a class like so:

    public class Person

    {

        public int PersonId { get; set; }

        public string PersonName { get; set; }

        public string LastUpdateUser { get; set; }

        public DateTime LastUpdateDate { get; set; }

 

    }

And a Factory (Builder, really) with the usual get and update interface like so:

    public class PersonFactory

    {

        public static Person GetPerson()

        {

            //Implementation

        }

 

        public static void UpdatePerson(Person person)

        {

            //Implementation

        }

    }

He then had a webpage with an ObjectDataSource and DetailsView. 

The crux of the discussion surrounding the LastUpdateId and LastUpdateTime and where to populate that value.  On one hand, the business layer is responsible for controlling the data so  it makes sense for the lastUpdateDate to be popualted in the Update Method of the Factory like so:

person.LastUpdateDate = DateTime.Now;

However, how do you update the LastUpdateUser in the business layer?   You would need to change the interface of the Update method to be something like this:

        public static void UpdatePerson(Person person, string lastUpdateUser)

        {

            //Implementation

        }

Which smells like Interface polution and certainly more regid than I would want.

On the other hand, you can populate the Person object in the UI via the code behind fairly easily:

protected void ObjectDataSource1_Updating(object sender,

            ObjectDataSourceMethodEventArgs e)

        {

            Person person = e.InputParameters[0] as Person;

            person.LastUpdateId = User.Identity.Name;

            person.LastUpdateDate = DateTime.Now;

 

        }

And I love easy.  In addition, just because you don’t code it doesn’t mean it doesn’t exist.  In this case, the Details View and ODS are responsible for hydrating the values of the Person object from the values in the controls (persisted across sessions by the view state) so it actually is more consistent to populate the values in the code-behind on the UI than in the data layer.

The point is, the code has to be written somewhere so why not put it in a place that is both consistant and keeps your Business Layer’s API clean?

Validation Block – Conditional Validation Redux

You can see my initial thoughts on conditional validation here.  I have a follow-up problem that required a different approach (and a Kludge).  The regular expression solution attribution validation solution only works for the single property.  What about validation for Two (or many) properties?  For example, assume you have a Person Class like so:

    public class Person

    {

        public int PersonId { get; set; }

        public string PersonName { get; set; }

        public DateTime DateOfBirth { get; set; }

        public DateTime DateOfDeath { get; set; }

 

 

        public override string ToString()

        {

            return PersonName;

        }

    }

Adding some simple attribute validation gives us this:

    public class Person

    {

        public int PersonId { get; set; }

        [StringLengthValidator(10, MessageTemplate = "Name is 10 characters")]

        public string PersonName { get; set; }

        [DateTimeRangeValidator(DateTime.Today, MessageTemplate = "Can’t be born in the future")]

        public DateTime DateOfBirth { get; set; }

        public DateTime DateOfDeath { get; set; }

 

 

        public override string ToString()

        {

            return PersonName;

        }

    }

But I have one more validation I need to implement – a person can not have a DateOfDeath before their DateOfBirth.

My First thought was to in-line a DateTimeRangeValidator like so

        [DateTimeRangeValidator(this.DateOfBirth, MessageTemplate = "You Can’t Die Before You are Born")]

        public DateTime DateOfDeath { get; set; }

However, you get this error – Keyword this is not available in the Current Context

 Note that you CAN do it for static fields, but that won’t help with 95% of the DTOs out there because DTOs are usually implemented as instance members – especially in a web solution.

 

My next thought was to use Self-Validation like so:

    [HasSelfValidation]

    public class Person

    {

        public int PersonId { get; set; }

        [StringLengthValidator(10, MessageTemplate = "Name is 10 characters")]

        public string PersonName { get; set; }

        [DateTimeRangeValidator(DateTime.Today, MessageTemplate = "Can’t be born in the future")]

        public DateTime DateOfBirth { get; set; }

        public DateTime DateOfDeath { get; set; }

 

        [SelfValidation]

        public void CheckDates(ValidationResults results)

        {

            if (DateOfBirth > DateOfDeath)

            {

                ValidationResult validationResult = new ValidationResult("DOB > DOD",

                    this, string.Empty, string.Empty, null);

                results.AddResult(validationResult);

            }

        }

 

        public override string ToString()

        {

            return PersonName;

        }

    }

This works fine in unit testing.  The problem is that the PropertyProxyValidation in ASP.NET solutions do not work with conditional validation – they only work with Attribute-based validation.  I seemed to be stuck (and I still am, really) so I came up with a Kludge.

I added a validator to the DateOfDeath Property like so:

        [DateTimeRangeValidator("1900-01-01T00:00:00", MessageTemplate = "You Can’t Die Before You are Born", Ruleset

        = "Zombie")]

        public DateTime DateOfDeath { get; set; }

 

Note the addition of the ruleset.

I then added a PropertyProxyValidator to the DateOfDeath field with the enabled Property set to false:

 

I then created a method in the code-behind of the web-page creates a new instance of the Person class using the fields from the web form and runs validation.   You need to run this validation before any data binding to keep in align with the Page lifecycle.

 

        private void BirthDeathDateValidation()

        {

            TextBox textBoxPersonId = this.DetailsView1.FindControl("TextBox4") as TextBox;

            TextBox textBoxPersonName = this.DetailsView1.FindControl("TextBox2") as TextBox;

            TextBox textBoxPersonDOB = this.DetailsView1.FindControl("TextBox1") as TextBox;

            TextBox textBoxPersonDOD = this.DetailsView1.FindControl("TextBox3") as TextBox;

 

 

                Person person = new Person();

                person.PersonId = Int32.Parse(textBoxPersonId.Text);

                person.PersonName = textBoxPersonName.Text;

                person.DateOfBirth = DateTime.Parse(textBoxPersonDOB.Text);

                person.DateOfDeath = DateTime.Parse(textBoxPersonDOD.Text);

 

                Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResults results =

                    new Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResults();

                person.CheckDates(results);

 

                if (results.Count > 0)

                {

                    PropertyProxyValidator propertyProxyValidator =

                        this.DetailsView1.FindControl("PropertyProxyValidator3") as PropertyProxyValidator;

                    propertyProxyValidator.RulesetName = "Zombie";

                    propertyProxyValidator.Enabled = true;

                }

            }

 

        }

 

Now, if the DateOfDeath happensbefore DateOfBirth, the ruleset is switched to the appropriate ruleset and the validator is enabled.

 

Like I said, a Kludge, but I don’t see a better option.

Unit Testing and DTOs

I have been studying for the MCPD-Enterprise 3.5 exam this last week so I have been going though MSFT’s training materials.  I started with the 70-561 book and I noticed that each of the examples include a Unit Test.  I thought this was really cool – it is the 1st training kit I have seen that integrated Unit Tests.

 

MCTS Self-Paced Training Kit (Exam 70-561): Microsoft .NET Framework 3.5 - ADO.NET

Speaking of Unit Tests, I also have been playing around with Unit Testing in a side project that I have.  I built a dedicated DTO class (complete with Ent Lib validation), built my 1st factory method that serves up the DTO (CRUD and collections), and then created a Unit Test to test the Get Method.

I figured out quickly that reference types do not work like this:

            int AgeGroupId = 1;

AgeGroup expected = new AgeGroup(1, "Boys 6 And Under", "6 And Under", 1, "15 Yards", 1, "Male", 1);

            AgeGroup actual = AgeGroupFactory.GetAgeGroup(AgeGroupId);

Assert.AreEqual(expected, actual);

 

Because they are two different pointers pointing to two different locations on the heap.  I then thought about comparing each property like so:

 

            Assert.AreEqual(expected.AgeGroupId, actual.AgeGroupId);

            Assert.AreEqual(expected.AgeGroupDesc, actual.AgeGroupDesc);

            //ETC…

 

But that seemed like a huge pain to code each property.

Next, I thought about implementing the IEquatable<T> interface and build something like:

Assert.IsTrue(expected.Equals(actual));

But then I am still coding each property – though it is in a better place.  Finally, I thought about using the ToString() method that I already implemented in the DTO.  That worked the best for me – primarily because I had already coded it and I only added in the properties that are unique/important.

Assert.AreEqual(expected.ToString(), actual.ToString());

I might go back to the IEquatable<T> interface in the future – just to make the API more predictable.

I wonder how Mocking handles this – I will know more about that once I implement MOQ in my project (next month hopefully…)

ASP Menu Trimming

I am on vacation this week but I wanted to share something that I found regarding ASP.NET Menu Trimming.  I was having a hard time understanding how the sitemap and the authorization section of the web.config work togeather.  This post gave the best explination of how it all works togeather.