Partial Page Post-Back and The Property Proxy Validator

I ran into a problem recently that had me scratching my head.  I have a DTO with Enterprise Library Validation like so:

    public class Person

    {

       

        [RangeValidator(0,RangeBoundaryType.Inclusive,10,RangeBoundaryType.Inclusive,MessageTemplate="{0} is an invalid Person Id")]

        public int PersonId { get; set; }

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

        [NotNullValidator(MessageTemplate="{1} Can’t be null}")]

        public string PersonName { get; set; }

        public DateTime DateOfBirth { get; set; }

        public DateTime? DateOfDeath { get; set; }

 

This person class was served up by a Factory (Builder, really) like so.  I threw some test data into the class just so I can inspect value in the round trip

 

    [DataObject(true)]

    public class PersonFactory

    {

        static Collection<Person> family;

 

        static PersonFactory()

        {

            family = new Collection<Person>();

            family.Add(new Person(0, "Jackie", DateTime.Parse("05/04/1951"), null));

            family.Add(new Person(1, "Tito", DateTime.Parse("10/15/1953"), null));

            family.Add(new Person(2, "Jermaine", DateTime.Parse("12/11/1954"), null));

            family.Add(new Person(3, "Marlon", DateTime.Parse("03/12/1957"), null));

            family.Add(new Person(4, "Michael", DateTime.Parse("08/29/1958"), DateTime.Parse("06/25/2009")));

        }

 

        public static Collection<Person> GetFamily()

        {

            return family;

        }

 

        public static void UpdatePerson(Person person)

        {

            . . .

        }

 

 

        public static void InsertPerson(Person person)

        {

            . . .

        }

 

I then created a simple Web Form to handle the updating using an Object Data Source and a Grid View:

<asp:GridView ID="GridViewFamily" runat="server" AutoGenerateColumns="False"

    DataSourceID="ObjectDataSourceFamily">

    <Columns>

            <EditItemTemplate>

                <asp:TextBox ID="TextBoxPersonId" runat="server" Text=’<%# Bind("PersonId") %>‘></asp:TextBox>

                <cc1:PropertyProxyValidator ID="PropertyProxyValidatorUpdatePersonId" runat="server"

                    ControlToValidate="TextBoxPersonId" PropertyName="PersonId"

                    SourceTypeName="TestWebProject.Person" Display="None"></cc1:PropertyProxyValidator>

                <cc2:ValidatorCalloutExtender ID="PropertyProxyValidator_UpdatePersonId_ValidatorCalloutExtender"

                    runat="server" Enabled="True" TargetControlID="PropertyProxyValidatorUpdatePersonId">

                </cc2:ValidatorCalloutExtender>

            </EditItemTemplate>

            <ItemTemplate>

                <asp:Label ID="Label1" runat="server" Text=’<%# Bind("PersonId") %>‘></asp:Label>

            </ItemTemplate>

        </asp:TemplateField>

        <asp:TemplateField HeaderText="PersonName" SortExpression="PersonName">

      . . .

 

    </Columns>

</asp:GridView>

 

So far, so good

 

 

I then added a Details View for inserting and associated it with the same Object Data Source:

<asp:DetailsView ID="DetailsViewInsertFamily" runat="server" AutoGenerateRows="False"

DataSourceID="ObjectDataSourceFamily" DefaultMode="Insert" Height="50px"

Width="125px">

    <Fields>

            <InsertItemTemplate>

                <asp:TextBox ID="TextBoxInsertPersonId" runat="server"

            Text=’<%# Bind("PersonId") %>‘></asp:TextBox>

                <cc1:PropertyProxyValidator ID="PropertyProxyValidatorInsertPersonId" runat="server"

            ControlToValidate="TextBoxInsertPersonId" PropertyName="PersonId"

            SourceTypeName="TestWebProject.Person" Display="None"></cc1:PropertyProxyValidator>

                <cc2:ValidatorCalloutExtender ID="PropertyProxyValidator_InsertPersonId_ValidatorCalloutExtender"

            runat="server" Enabled="True"

            TargetControlID="PropertyProxyValidatorInsertPersonId">

                </cc2:ValidatorCalloutExtender>

            </InsertItemTemplate>

            <ItemTemplate>

                <asp:Label ID="Label1" runat="server" Text=’<%# Bind("PersonId") %>‘></asp:Label>

            </ItemTemplate>

        </asp:TemplateField>

            . . .

 

 

    </Fields>

</asp:DetailsView>

 

Things go awry.   When I try and run an update on the screen, I get the following error:

Index was outside the bounds of the array.

After a little thought, I realized that the Insert Template is firing off the validation on the update postback.  I handled the error by adding a ValueConvert event handler to the PropertyProxyValidator on the insert:

        protected void PropertyProxyValidatorInsertPersonId_ValueConvert(object sender, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.ValueConvertEventArgs e)

        {

            int result = 0;

            bool ok = Int32.TryParse(e.ValueToConvert.ToString(), out result);

            if (!ok)

            {

                e.ConvertedValue = -1;

            }

        }

However, handling the error then gives me this:

 

Notice how the Validator is firing for Details View – even though the Updating is from the Grid View.

I then put the details view into an Update Panel to see if that will isolate the GridView’s Update – no luck.  I then thought of two programic solutions:

·         On the Updating Event, disable the Insert Validators

·         Adding a RuleSet for updating and inserting

Both solutions seem less than ideal to me – Adding a ruleset uses duplicates code and makes the code base harder to maintain – as well as coupling the DTO to the User Layer – which is never good.  Using some event to enable/disable the validators seems to be better from a coding perspective so I will implement that

 

 

 

WCF – My “Duh!” moment of the week

In preparation for my 70-569 exam, I have been following the Learning Plan for WCF found here
The first step was this webcast found here

I attempted to build a Hello-WCF solution based on what as presented in the webcast and I <thought> I ran into Vista problems.  I set my endpoint like this in the Hosting Service:

serviceHost.AddServiceEndpoint(typeof(IPersonFactory), new NetTcpBinding(), "net.tcp://localhost:9000/PersonFactory");

And I set a reference to that endpoint in the client like this:

IPersonFactory proxy = ChannelFactory<IPersonFactory>.CreateChannel(new

      NetTcpBinding(),new

EndpointAddress("net.tcp://localhost:9000/PersonFactory"));

 

Console.WriteLine(proxy.Echo("Hello World"));

 

I got the following message:


No connection could be made because the target machine actively refused it 127.0.0.1:9000

I tried running VS2008 as an administrator but I got the same message.  I then opened the port in Windows Firewall and then disabling the firewall completely.

I then posted to the MSDN forums here

 

Turns out I was barking up the wrong tree.  By using the “Using” statement, I was closing the port before attempting to have the client make the call.  I quess I was too quick to blame Vista…

MCPD Upgrade

I passed Exam 70-568 on Friday.  I was surprised about how little of the new features of 3.5 were actually in the exam – only a few questions on LINQ, none on entity framework, etc….  I guess the 4.0 exam might have it?  In any event, I am planning to finish the 3.5 upgrade this Decemeber so I am jumping into WCF with both feet.
 

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?