10

I have a pretty simple ASP.NET page with some input fields and validators. One field accepting a double looks like this:

<asp:TextBox ID="tbHeight" runat="server" />
<asp:RangeValidator ID="vdHeight" runat="server" 
    ErrorMessage="Height must be a positive number" Text="*" 
    ControlToValidate="tbHeight" MinimumValue="0" Type="Double" />

This works as expected, and the user must enter a number >= 0.
Update: this does not work as expected afterall (some weird bug in the project). See comments to the answers below for details

I then try the same for a field accepting an integer:

<asp:TextBox ID="tbGrossTonnage" runat="server" />
<asp:RangeValidator ID="vdGrossTonnage" runat="server" 
    ErrorMessage="Gross Tonnage must be a positive whole number" Text="*" 
    ControlToValidate="tbGrossTonnage" MinimumValue="0" Type="Integer" />

When loading the ASP-page, this gives me the following error: The value '' of the MaximumValue property of 'vdGrossTonnage' cannot be converted to type 'Integer'.

I don't have any specific max value requirements in the system, so I would just like it to "default" to Int32.MaxValue (although I'd have to enter 2,147,483,647, since MaximumValue doesn't seem to accept the Int32.MaxValue constant).

Why is it that a RangeValidator of the type Integer won't accept a missing MaximumValue property, but for one of the type Double this is ok?

Julian
  • 20,008
  • 17
  • 77
  • 108

4 Answers4

15

The MinimumValue and MaximumValue properties of the RangeValidator class return string.Empty as their default when not set.

Next, it also happens that the Convert() protected method implemented by BaseCompareValidator, which is used for converting the string properties to values, calls int.Parse() for the ValidationDataType.Integer case. int.Parse() doesn't like the empty string and will throw an exception.

But, in the case of ValidationDataType.Double, Convert() first calls another protected method, ConvertDouble() (instead of double.Parse()), and in that method it explicitly returns a string value of "0" when an empty string is detected, and that string value "0" later parses, via double.Parse() into 0d.

The integer case doesn't benefit from such a mapping of string.Empty to "0".

Hence, the dicrepancy. The devil is in the details, and Reflector is your friend.

Chris W. Rea
  • 5,430
  • 41
  • 58
  • Just a small follow-up: in the case that I leave out `MaximumValue` for the double type, this would then really mean that both min and max are 0. Why then does my page validate the field correctly (-1 is invalid, and 1 is valid (I have double-checked, and this really works))? – Julian Mar 23 '11 at 14:04
  • @Nailuj I can't corroborate your finding that the page validates correctly with "1" as input. If I drop your controls (from your first snippet above) onto a new page in an empty web site project, inputting "1" and then causing postback (I added a button) *does* cause validation failure. – Chris W. Rea Mar 23 '11 at 14:14
  • An Additional thing to note is that it seem to do a string compare for date fields not a date compare so a Range validator that will accept 01/12/2016 wont accept "01 Dec 2016" – MikeT Dec 16 '16 at 12:10
1

Leaving the MaximumValue blank on Type="Double" is equivalent to setting MaximumValue to 0. I'm not sure you are right about the first of your examples working fine.

matt-dot-net
  • 4,204
  • 21
  • 24
  • Yes, I *am* sure my first example works fine. I've double-checked this (see my comment to Chris W. Rea's answer). – Julian Mar 23 '11 at 14:06
  • @Nailuj I tried your example and it didn't work fine. (See my comment above.) Can you try again in the simplest possible reduced case, outside your application, in a new web site project, as I did? Perhaps there's other code from your application interfering. e.g. Do you selectively enable/disable any of your validators? etc. – Chris W. Rea Mar 23 '11 at 14:18
  • @Chris W. Rea: I tried with a new ASP.NET project, and in this case I got the same result as you: the validation does *not* work fine. I cannot think of anything obvious in my other application that might cause this either... But it doesn't really matter, I'll just make sure to explicitly specify both min and max value. Thanks for taking the time to test it :) – Julian Mar 23 '11 at 14:28
  • @Nailuj If it were me, I'd want to get to the bottom of it so I could grok exactly what's going on. Try removing parts one-by-one (then re-test) of your "inexplicably working fine" page until you've reduced it to the point where validation starts to fail... then that last thing you removed is the likely culprit. If you don't do this, you might be leaving a bug for your colleagues to find later ;-) – Chris W. Rea Mar 23 '11 at 14:32
  • @Chris W. Rea: yes, that would indeed be the responsible thing to do. And in a perfect world I would very much like to do so too. However, this project is so large with so much spaghetti that it wouldn't really be feasible. It hurt a little bit inside saying so, but with limited time and resources this is the reality one sometimes just have to cope with :-/ – Julian Mar 23 '11 at 14:40
0

Just to make it more confusing..

In my formview (which is in an updatepanel if that makes any difference) I have..

<div class="Width100PercentPadded">
    <div class="Width40PercentPadded FloatLeft ClearLeft">
        Latitude:
    </div>
    <div class="Width60PercentPadded FloatLeft">
        <asp:TextBox runat="server" ID="txtLatitude" CssClass="Width100Percent" Text='<%#     Bind("Latitude") %>' ></asp:TextBox>
        <asp:CompareValidator ID="CompareValidatorLatitude" runat="server" ControlToValidate="txtLatitude" Operator="DataTypeCheck" Type="Double" ErrorMessage="Latitude must be  numeric" Text="must be numeric" ForeColor="Red" Display="Dynamic"></asp:CompareValidator>
        <asp:RangeValidator ID="RangeValidatorLatitude" runat="server" ControlToValidate="txtLatitude" MinimumValue="0" MaximumValue="90" ErrorMessage="Latitude in range 0 to 90" Text="range 0 to 90" ForeColor="Red" Display="Dynamic"></asp:RangeValidator>
    </div>
</div>

<div class="Width100PercentPadded">
    <div class="Width40PercentPadded FloatLeft ClearLeft">
        Longitude:
    </div>
    <div class="Width60PercentPadded FloatLeft">
        <asp:TextBox runat="server" ID="txtLongitude" CssClass="Width100Percent" Text='<%# Bind("Longitude") %>'></asp:TextBox>
        <asp:CompareValidator ID="CompareValidatorLongitude" runat="server" ControlToValidate="txtLongitude" Operator="DataTypeCheck" Type="Double" ErrorMessage="Longitude must be numeric" Text="must be numeric" ForeColor="Red" Display="Dynamic"></asp:CompareValidator>
        <asp:RangeValidator ID="RangeValidatorLongitude" runat="server" ControlToValidate="txtLongitude" MinimumValue="0" MaximumValue="180" ErrorMessage="Longitude in range 0 to 180" Text="range 0 to 180" ForeColor="Red" Display="Dynamic"></asp:RangeValidator>

    </div>
</div>

Note my latitude and longitude validation is essentially the same except Longitude allows a higher maxvalue.

When running, Longitude is validated exactly as expected - type must be numeric and value must be between 0 and 180.

Latitude type must be numeric, and range fails if value is negative, but the maxvalue is not checked. I can put values in the millions in the textbox and validation does not fail.

user981235
  • 161
  • 1
  • 1
  • 4
0

It is best practice to specify MaximumValue for the RangeValidator even if your requirements does not specifically call for one. In that case just use the MaxValue for the Type. The default value for MaximumValue is String.Empty.

Kris Ivanov
  • 10,476
  • 1
  • 24
  • 35