Skip to main content

Data Validation with Non-Inclusive Range Validator

The other day I was doing some validation for a few of my class's numeric properties. The valid range, I was told, was 0 to infinity. That's easy enough, I told myself. I'll just put a [Range] attribute each property and let the framework do its thing, like so...

[Range(0,double.MaxValue,ErrorMessage="Please specify a value greater than or equal to zero.")]

After publishing the web site to the staging server, I got an email from the client saying that 0 was not a valid value for some of the properties. My first thought was simply to change my range attribute this way:

Range(0.00000000001,double.MaxValue,ErrorMessage="Please specify a value greater than or equal to zero.")]

After all, who's going to type that many zeros? I still wasn't happy with that solution, so I started considering my alternatives. IDataErrorInfo was a definite option, and that would look this:

public string this[string propertyName]
      switch (propertyName)
          case "NonZeroNumericProperty":
              if (NonZeroNumericProperty == 0) return "Please enter a value greater than zero";

Notice that I only checked for a value equal to zero, as the Range attribute still makes sure that the value isn't less than zero. I have two problems with this approach: the first is that my validation for this property is sitting in two different places. The second is that the "this" property from IDataErrorInfo gets really long and ugly really fast. Sure, sometimes there is no better way, but in this case, I think I found one that is both elegant and lets me keep my validation rules together near the relevant property where it can be seen and easily changed.

So I created a new custom validation attribute called NonZeroAttribute that makes sure the property's value isn't zero. Combined with the [Range] attribute, I get everything I wanted.

/// Ensures that an object's value is not equal to zero.
public class NonZeroAttribute : ValidationAttribute
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        ErrorMessage = "Please enter a value that is not equal to zero.";
        var badResult= new ValidationResult(this.ErrorMessageString) ;

        if (value == null) return null;

        double x = 0;
        if (double.TryParse(value.ToString(), out x) == false)
            return badResult;

        ValidationResult result = value.Equals(0.0) ? badResult: null;
        return result;

The function first checks to see if the value is null. If it is, we let it go. We leave it up to the coder to use a [Required] attribute if necessary. Then we try to parse the object's value into a double. I chose a double because any numeric value should be able to be converted into a double safely. If the TryParse fails, the value is non-numeric. In that case, we return a bad result. I may have to rethink that part, because a non-numeric value is clearly "not zero." Finally, the parsed numeric value is compared to 0 and the result returned. So far, it works like a charm.

With that class in place, I can easily remove my IDataErrorInfo code above and annotate the properties with the appropriate attribute(s);

public double NonZeroProperty

I'd be curious to hear others' thoughts on the pros and cons to this approach, as well as any optimizations I could make.


Popular posts from this blog

How to copy your Frozen Free Fall progress to a new phone

It's happened to all of us. You are about to get a branch new smartphone, when it hits you. You're on level 250 of Frozen Free Fall. If you get a new phone, you'll lose all of that progress! Ok, admittedly this isn't the most pressing problem of our time, but it's annoying. So today I decided to do something about it.

I have a Samsung Galaxy S4 (Android), and just received an iPhone 5c. Before you bash me on my phone choice, let me explain that the iPhone is provided by my employer at no cost to me. Now you may proceed to bash me for putting games on my work phone. 
First step: Frozen Free Fall had already been installed on both devices. Next, using the Astro File Manager on my Galaxy, I searched and found the Frozen game save stored in /storage/sdcard0/Android/data/com.disney.frozensaga_goo/files/user.dat. I imagine it will be in the same location on any Android phone. If not, just look for user.dat in a folder with a similar name. So, using a USB cable and the A…

Ionic vs. Bootstrap - for a Web App

Ionic 1.x vs Bootstrap 3.x for a Web AppI was recently asked at work to come up with a comparison between Ionic Framework and a more traditional Angular/Bootstrap combination to create a web app. The application will primarily be used in a desktop web browser (probably Chrome or IE). There are also some use cases where it will be accessed from Safari on an iPad. However, this is purely a web; there are no plans to install the app onto the iPad as a hybrid app. Thus, recommending Ionic to build the UI hadn't occurred to me until the request was made.

This is even more surprising in that I recently published a Pluralsight course on Ionic Framework 1. It should have been the first thing that crossed my mind.
One constraint is that currently only Angular 1.x and Bootstrap 3 are authorized web technologies. Ionic 1.3 was recently approved, but not Ionic 2, Angular 2, or TypeScript yet.
Given those constraints, herein is my attempt at coming up with reasons to use (or not to use) Ionic…

Ionic + StencilJS = Slot Machine

Ionic + StencilHi, this is Mike Callaghan, and today I want to make a simple slot machine. This is a follow up to my recent video on creating my very first stencil web component. In that video, I added the component to an existing ionic app, but I really glossed over how that happens.
Today I'm going to go through the steps necessary to take an existing StencilJS web component, and create a working mobile app from scratch with the Ionic Framework that uses three instances of that component. The StencilJS componentLet's start with the web component. I created it a few weeks ago to see how to get CSS 3D animation working with Stencil. My goal was to create a component I could use multiple times on a page, without the component needing to know or care what the images are that it's animating, or how many there are. All of that is determined dynamically. Show the github repoI'm not going to go through the code here at all. Here is the public GitHub repo if you want to check t…