Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

General purpose CustomValidator

Status
Not open for further replies.

Glasgow

IS-IT--Management
Jul 30, 2001
1,669
GB
I'm pretty new to ASP.NET and so finding my way but I was wondering whether it's possible to set up a single general purpose OnServerValidate routine that triggers different logic and error messages. Something along these lines..
Code:
Select Case Control.Name
  Case "TxtBox1"
    if ucase(TxtBox1.Text)<>TxtBox1.Value) then args.isvalid = False
  Case "TxtBox2"
    if Instr("a,c,d,e",TxtBox2.Text)<1 then args.isvalid = False
End Select
Excuse any typos - I'm just trying to illustrate the approach. I'd still like to be able to trigger the error message associated with the individual CustomValidator controls assuming I can't assign these in the same general purpose routine.

I accept that I may have missed the point completely!
 
you can, but i would advise against it. A CustomValidator is general by it's nature. OOP is about encapsulating change. in this case you have 4 things that could change, a single event handler
1. name of control
2. type of control
3. new validation
4. different (but existing) validation
by using either a subclassing or unique specification approach you can isolate change.

subclassing the CustomerValidaor would look like this.
Code:
public class MyValidator : CustomValidator
{
   //override members as necessary
}
here is an example of moving the actual logic out of the code behind and into a specification.
Code:
interface ISpecification<T>
{
   bool IsSpecifiedBy(T item);
}

class EqualsSpecification<T> : ISpecification<T>
{
   private T other;

   public EqualsSpecification(T other)
   {
      this.other = other;
   }

   public bool IsSpecifiedBy(T item)
   {
       return item.Equals(other);
   }
}
now my CustomerValidator handler would look like this.
Code:
protected void Validated(object sender, ServerEventArgs e)
{
   var other = TextBox1.Text;
   var item = e.Value;
   var spec = new EqualsSpecification<string>(other);
   e.IsValid = spec.IsSpecifiedBy(item);
}
this approach is nice because if the requirements change. (Say the values should not be equal) I can add logic with minimal changes to the existing code.
Code:
public class NotSpecification<T> : ISpecification<T>
{
    private ISpecification<T> spec;
    public class NotSpecification(ISpecification<T> spec)
    {
       this.spec = spec;
    }

    public bool IsSpecifiedBy(T item)
    {
       return !spec.IsSpecifiedBy(item);
    }
}
and a change to customvalidator event.
Code:
protected void Validated(object sender, ServerEventArgs e)
{
   var other = TextBox1.Text;
   var item = e.Value;
   var spec = new EqualsSpecification<string>(other);
   var not = new NotSpecification<string>(spec);
   e.IsValid = not.IsSpecifiedBy(item);
}
I have added new code. i did not need to change my existing specification. the changes to the validation event handler were minimal (1 line of code).

on the other side, if you change the control from a textbox to a dropdown list, only the handler needs to change, not the specification.

another added bonus with this approach; the code behind becomes a thin wrapper around the actual logic.

Jason Meckley
Programmer
Specialty Bakers, Inc.

faq855-7190
faq732-7259
 
Thanks Jason. Phew. I was hoping for something my sad old "Classic ASP/VbScript" brain could handle. C# is just one step too far for me at the moment when I'm struggling enough with both ASP.NET and ADO.NET basics.

I'll take a look at this tomorrow and see if I can translate into VB but I'm not optimistic! I should have stated that I'm working in VB, sorry - I guess I'd assumed my pseudo-code would give that away. I appreciate the help though.
 
ok, i'll try to simplify this some :) OOP is all about encapsulation and isolating change. This concept is quickly understood but it can take a life time to master :)

when you place a custom validator on the form you are creating a new instance of the CustomValidator object. so with this single instance we can encapsulate the the logic associated with that. if we place all the custom logic in this control with a switch statement it really just becomes a global container for validation. debugging this would also become complicated because of all the various code paths you need to test.

here are some of the details on the specification pattern I outlined above.
1. we start with an abstraction. that's just a fancy term for contract. The code calling the contract doesn't care how it works, only that it will work. for example: our event handler above asks "is this specified? yes or no". How it's specified is determined by our implementation.

2. implementing the abstraction/contract above we have 2 implementations. Equals and Not. Equals is pretty straight forward. are 2 objects equal. Not simply says "ok, whatever this specification is, take the opposite" true becomes false and false becomes true. each implementation encapsulate the logic. we could also create specifications for greater than, less than, contains, etc.

by mixing a matching these implementations we can get a right set of validation with only a few simple objects. the fancy term for this is composition.

back to your original question though. I think to start off, simply create a new custom validator for each piece of logic on the page. As you find similarities both within and among pages consider moving that to a common object. which can be used across multiple scenarios.



Jason Meckley
Programmer
Specialty Bakers, Inc.

faq855-7190
faq732-7259
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top