Chorn Sokun's Weblog

Conquer inner fear, push it to the limit!

Rhino-Tools a smarter Guard

with 4 comments

When Ayende typed Guard.Against(condition, error_message) it clicked in my brain. I thought wow that was nice and easy to use what it does was check if the condition is true it will throw and exception with error message specify. I had an idea using this litle beast for business validation, since it doesn’t required any special configuration all you have to do is adding reference to Rhino.Common.Clr.dll.

However the original Guard API only has only two static method Guard.Against() it was limited for web application. In web application we might want to report back all problems so user can make the correction before they re-submit the form again, but using Guard.Against() we only catch one problem at a time, if we have multiple codition to check you can imagine how annoy for web experience.

Ayende is kindly enough accepting my patch for two additional method for the Guard bellow:

  • Guard.Check(condition, error_message) – same behavior as Guard.Against() but it won’t throw and exception instead keeping records of problems
  • Guard.Report() – until .Report() get call and exception known as GuardSpotException will be throw.

Let see how I can improve my usage experience with these methods

try{
  new Guard()
    .Check(pay.Date.Equals(DateTime.MinValue), "Invalid payment date.")
    .Check(pay.Amount == 0, "Invalid amount, should it be something other than zero?")
    .Report();

  // persist pay instance to the database
}
catch(GuardSpotException ex)
{
  // list of errors message
  PropertyBag["errors"] = ex.GetErrorSummary();
}

First I instantiate a new Guard object and start checking conditions (business rules) finally I call Guard.Report() if there is any true condition (= business rule voilated) and exception known as GuardSpotException will be throw you then can catch and examin all problems.

Isn’t that cool?

Advertisements

Written by Chorn Sokun

April 10, 2009 at 10:37 am

4 Responses

Subscribe to comments with RSS.

  1. Nice way to validate input, but don’t you think about using validation frameworks instead, because we don’t want to repeat from controller to controller, we want to keep it in one place.

    I have ever used similar thing(DBC) http://www.codeproject.com/KB/cs/designbycontract.aspx, but not for validating models.

    Samnang

    April 10, 2009 at 11:59 am

  2. I thought about NHV, Castle Validation etc.
    But I prefer to handle the rule myself in general I would wrap validation logic like:

    Service.dll

    TryDelete(entity)
     new Guard()
       .Check(...)
       .Check(...)
       .Check(...)
       .Report();
    
    DeleteEntity(entity)
      TryDelete(entity);
      // ... deleted
    

    From controller point of view I can do:
    When request for delete an entity

    public void RequestDelete(Entity entity){
       try{
          Service.TryDelete(entity);
       }catch(GuardSpotException ex){
          // extract detail error summary
       }
    }
    
    public void RealDelete(Entity entity, string token){
      try{
        Service.Delete(entity);
      }catch(GuardSpotException ex){
        // extract detail error summary
      }
    } 
    

    it just all POCO no additional learning required.

    Chorn Sokun

    April 10, 2009 at 1:19 pm

  3. If so, how do you handle form validation on client side?

    Samnang

    April 10, 2009 at 3:31 pm

  4. jQuery validation I believe in Defend in deep user may by pass client-side validation.
    I can still report problems to the client via ajaxForm()

    Chorn Sokun

    April 10, 2009 at 4:09 pm


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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: