ValidationAttribute's value always null

Here's a simple validation attribute I wrote to enforce number-only strings (I use it to validate phone numbers, postal codes and alike):

public class NumericAttribute : ValidationAttribute {

    public NumericAttribute() {
        ErrorMessage = SharedModelResources.ValidationStrings.Numeric; // Message coming from a .resx file
    }

    public override bool IsValid(object value) {

        string stringValue = value as string;

        if (stringValue.IsNotNull())
            foreach (var c in stringValue)
                if (!char.IsDigit(c))
                    return false;

        return true;
    }

}

The problem is that when used to validate other than strings, let's say a decimal, short, int or anything else, object value is ALWAYS null. Why validate numeric only decimals? Because if I don't, I get the default validation message 'The value 'x' is not valid for 'propertyName'. I'm aware of the solutions for the specific problem of the default validation message.

I just want to understand WHY it's always null...

BTW, I'm using VS2008, ASP.NET MVC 2 (final), .NET 3.5 SP1.

Answers


Are you positive it is value that is null and not just stringValue?

So sayeth the MSDN about your as operator:

The as operator is like a cast except that it yields null on conversion failure instead of raising an exception.

http://msdn.microsoft.com/en-us/library/cscsdfbt%28VS.71%29.aspx

In the examples on that page it shows that numerics do not as to strings the way you want.

You might try .ToString() instead.


If your scenario is that you're trying to stick your validator on a property of type int, decimal, etc., and the value coming in isn't convertible to int, decimal, etc., then this is intentional.

Consider what you're asking the MVC framework to do. The property is of type int, so the MVC framework is working with values of type int. (Technically, it's working with something more akin to Nullable<int>.) If the incoming value isn't convertible to int, there's no way to represent that in a Nullable<int> other than null since that type can't contain arbitrary strings. So that's why your validation attribute ends up getting null as a value.

Edit:

If you want to control this error message, the easiest option is to change the property to a string, then have your custom validator call Int32.TryParse or whatever you need it to do in order to verify that what the user typed is numeric. Then you can have a separate read-only property that's basically the numeric form of that property's value.

More complex but more generalized, you could replace the built-in DefaultModelBinder with one of your own creation. From within the BindModel method, look for exceptions of type FormatException in ModelState, then replace them with the error message of your choosing. See the end of the method DefaultModelBinder.BindProperty for an example of how this is done.


Need Your Help

File Server Indexing Service for Mac OS Search

fileserver file-search indexing-service

Has anyone a solution for getting the MAC spotlight search facility to work with a remote file server (turnkey pdc, Debian) connecting by SMB.

MySQL c connector: executing queries from separate threads

mysql-connector mariadb mysql

I create the connection to the server in the main thread of application:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.