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.

ASP.NET Role Provider

Once again proving that everything comes down to infrastructure, I have a frustrating problem regarding ASP.NET Role provider.  The requirements are very basic – I want a site map that controls menu trimmed based on the user’s role.  The implementation is less than basic.  Using the out-of-the-box Role Provider and Site Map from ASP.NET, I set up my site.  Then, I added some location tags to my web.config to govern what is accessible for the different roles.  Excerpts from my web.config: 

<connectionStrings>

<remove name="LocalSqlServer"/>

<add name="LocalSqlServer" connectionString="server=ActuallyARemoteServer;database=zzzzzz;User ID=yyyyyy;Password=xxxxxx;Connect Timeout=30" providerName="System.Data.SqlClient"/>

And the 2 providers:

<siteMap defaultProvider="default" enabled="true">

<providers>

<clear/>

<add name="default" type="System.Web.XmlSiteMapProvider" siteMapFile="web.sitemap" securityTrimmingEnabled="true"/>

</providers>

</siteMap>

<membership>

<providers>

<remove name="AspNetSqlMembershipProvider"/>

<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" passwordFormat="Hashed" maxInvalidPasswordAttempts="25" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>

</providers>

</membership>

And some resources. 

<location path="Default.aspx"> <system.web> <authorization>

<allow users="*"/>

</authorization> </system.web> </location>

<location path="Public"> <system.web> <authorization>

<allow users="*"/>

</authorization> </system.web> </location>

<location path ="Musician"> <system.web> <authorization>

<deny users="*"/>

<allow roles="Musician"/>

</authorization> </system.web> </location>

 

Interestingly, nothing showed on my menu bar until I added the "roles" attribute to the root node:

<siteMapNode url="" title="My Application Home" description="" roles="*">

 Which seems odd to me – but I’ll research some other day

The problems are now infrastructure.  I start up my Website Administration Tool and it points to the remote server and I add a role no problem.  When I try and add a user though, it bombs with this error message. 
Exception has been thrown by the target of an invocation. at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Web.Administration.WebAdminMembershipProvider.CallWebAdminMembershipProviderHelperMethodOutParams(String methodName, Object[] parameters, Type[] paramTypes) at System.Web.Administration.WebAdminMembershipProvider.CreateUser(String username, String password, String email, String passwordQuestion, String passwordAnswer, Boolean isApproved, Object providerUserKey, MembershipCreateStatus& status) at System.Web.UI.WebControls.CreateUserWizard.AttemptCreateUser() at System.Web.UI.WebControls.CreateUserWizard.OnNextButtonClick(WizardNavigationEventArgs e) at System.Web.UI.WebControls.Wizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.CreateUserWizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.Wizard.WizardChildTable.OnBubbleEvent(Object source, EventArgs args) at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
This seems odd to me – b/c the Roles are persisting fine.  I did a quick search on WebAdminMembershipProvider.CreateUser Error with Google/Bing and I found this link, which seems to be my problem.
Remove local ASPDB – Check
Add Machine Key – Check
Works – Not Check
 
Grrrr.  I’ll probably post there next.
  

Validation Block – Conditional Validation

I ran into an interesting problem today.  I am working on a DTO layer for a project at work and we want to use the Ent Lib Validation Block.  This is an ASP.NET application and ideally we will only use the PropertyProxyValidatior on our UI.  For Required fields, it is very straight forward – use the Date/Time, String Length, etc  Validators.  However, the problem comes when we need to evaluate optional (nullable) fields.  We have a couple of use cases:
prop is null or, if not null, only 4 characters in length
prop is null or, if not null, matches email regex
 
According to this post, The Validation Block does not support conditional validation in its attributes.  You can use Self Validation but then you can’t use the PropertyProxyValdiator as described here.  A search of ASP.NET forums also indicates that it can’t be done as described here.
 
To solve this problem, I came up with some adquate workarounds.  For use case #1, use the string length validation and set the base to 0.  For the second use case, put a conditional character ("|") in a reg exexpression.  For example:  [RegexValidator(@"(^.{0,0}$)|(^.{1,4}$)", MessageTemplate = "Need To Be Empty or 1-4 Characters")].  Note that use case #2 works with string.empty and string = "", but not with string = null.  That is ok, I have to make sure the UI calling code defaults to string.empty and it will work.  If anyone know how to do a regex for null, please pass it along (I search some but then gave up)

Fowler Architectural Patterns

I read the 1st couple of sections of Fowler’s Patterns of Enterprise Application Architecture.  I had trouble grasping his description of Transaction Script so I went ahead and built a project in C#.  I noticed a coupld of things.
 
1) APplication architecture is more about interfaces.  For example, the complex business logic in the Domain Logic Layer is found in RecognitionService.CalculateRevenueRecognition.  Instead of coding the logic in an Select…Case phrase, you can call a stored procedure and have the logic calculate on the database.  Is the application no longer Transaction Script?  If the function’s interface did not change, I would think it is still TS.  Hwoever, the logic is actaully on the data layer – or can part of the data tier have the domain logic?  I don’t see why not because the UI tier often holds the Domain Logic in fat-windows solutions.  ALso, I carved out the domain logic classes from the UI project to it’s own project in the solution.  Did I change the application architecture?
 
This got me thinking about 2-tier and n-tier use cases:
 
UI & DL & DB | SPS & DT where SPS only does CRUD to DT = n-tier
UI & DB | SPS & DT where SPS does CRUD and DL = 2-tier
UI & DB | SPS for CRUD, SPS for DL, & DT = 2-tier
 
Also, I am looking for patterns about types of Business Logic.  Fowler defines Domain Logic and Application Logic.  I don’t know to put rules regarding security  – is that another area, or layered in these 2 buckets.
 
More questions than answers at this point
 
 
 

LINQ To SQL – Part 01

I started playing around with LINQ to SQL This AM.  I tried to enumerate all of the running processes on my machine using the following LINQ:
 

var

query =

from p in System.Diagnostics.Process

.GetProcesses()

select new

{p.SessionId.ToString(), p.ProcessName};

ObjectDumper.Write(query);

  

and I got the following error:
Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.
An anonymous type must be declared with a member assignment, simple name, or member access.

Apparently, you need to have real variable names for each property you create (note the bold):

 

select

 new {sessionId = p.SessionId.ToString(), p.ProcessName};

Did the trick

 

Christmas Project Part 3

I did not complete the project – spent my December studying for MCPD Upgrade exams.  I am now offically a
 
So I have 2 exams in 2009 to upgrade to 3.5.   This means less time for fun coding and more time on WF/WCF/WPF and LINQ.  Oh well, if I get back to the project, I will post progress here

Christmas Project – Part 2

Most of sound examples I have seen revolve around visualization of the sound wave.  The application architecture has 2 threads – thread #1 plays the music, thread #2 runs as a continual loop.  In that loop, the app polls the sound card’s buffer and reads inforamtion out of that buffer.  Based on that information, it updates the display.  None of the examples I have seen actaully describe that buffer in detail – what each value of the return array means, for example.  I hope to get a better understanding via the MSDN documentation.  Also, I wonder what the maximum speed the mechanical switch of the phiget can run – can it keep up with 8th notes Con Brio?  We soon shall see…
 

Christmas Project – Part 1

In 2007, I put together a basic Holiday light show based on a great article in Coding4Fun by Brain Peek.  For 2008, I wanted to extend concept by reading any sound file and having the circuits respond to ‘major events’ in the audio file – much like the Visualizer in Windows Media Player does.  
 
Step one of the project is to figure out how to capture the sounds with the correct data (frequency, volume, direction) that I can pass to the light switches.  I first looked at using WMP SDK but that does not allow you to access the actual sound waves. 
 
I then looked on Codeplex and there are a bunch of old articles (2003) using Managed DirectSound and .NET 1.1 that allow you to capture the waves and inspect their values.  Unfortunately, they did not explain some of the data strucutres well enough for my needs.  I wondered if there is a more recent SDK with examples from Microsoft that I can use. This  task is not  as easy as it sounds because of the number of SDKs they put out there, the fact that some say they support C# but don’t include any samples or documentation (can you really call that support?), and the fact that some of their samples just don’t work.  Here is a list of the DirectX SDKs:
August 2008 – Only C++ and the samples  don’t work out of the box (missing ‘xaudio2.h’)
June 2008 – Only C++ samples – at least the samples work
March 2008 – Only C++ samples – this is getting annoying
November 2007 – Pre-release of XAudio2.  Only C++ examples
August 2007 – Pre-release of XAudio2.  Eurika!  Managed Samples (though only for .NET 1.1)
June 2007 –
April 2007 –
August 2006 –
 
So it looks like no .NET 2.0+ samples for Managed Code.  I wonder how long until MSFT gives an update.