简体   繁体   中英

Model binder can't handle double.MAX string representation back to double

Right now I have a ViewModel with a property double Maximum . On the view side it's kept in a hidden input to help with unobtrusive validation.

When post backing the values, the binding silently fails. I had to put a breakpoint on this line:

if(ModelState.IsValid)

and check which ModelState property had an error. Then I found that this double Maximum property had an error with the following message:

The parameter conversion from type 'System.String' to type 'System.Double' failed. See the inner exception for more information.

On the view side inspecting the HTML with Firebug I can see that the hidden input has this value:

1.79769313486232E+308

which correctly represents double.MAX constant.

I found this Scott Hanselman post from Jan/2005 (almost 9 years ago) which deals with something similar:

Why you can't Double.Parse(Double.MaxValue.ToString()) or System.OverloadExceptions when using Double.Parse

Is there something wrong with my app config or this direct conversion from string back to double is not supported? I think it should handle it without errors.

Note: I tried changing the hidden input value with Firebug and did as Scott mentions on his post: I subtracted 1 from the last digit...

1.79769313486231E+308

and did a postback again just to find the model binder handled it correctly this time.

I'm using @Html.HiddenFor to create the hidden input.

After carefully reading Scott's post I saw that he mentions the round-trip specifier. I also found an example here on StackOverflow.

The R stands for "round-trip". From MSDN :

This format is supported only for the Single and Double types. The round-trip specifier guarantees that a numeric value converted to a string will be parsed back into the same numeric value.

So I did this:

@Html.HiddenFor(m => m.Maximum,
                new { Value = Model.Maximum.ToString("R") })

Now this gives me a double.MAX string representation that can be round-tripped back to a double on the controller side:

1.7976931348623157E+308

Nice... problem solved.

Hope it helps anyone that might face this same problem in the future.


How interesting this is?!

1.79769313486232E+308   // double.MAX
1.7976931348623157E+308 // double.MAX.ToString("R")

It's worth mentioning that all this is also applicable to double.MIN .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM