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

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: