-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Model binder doesn't validate decimals with thousands separator #5502
Comments
@frankabbruzzese the If yes, suggest replacing the Another possibility is the server isn't changing the culture in each request. You may need to add |
@dougbu , unluckly I am sure 99% the problem exists (100% is impossible with software :)). Problem may be reproduced in 10 minutes:
Just to be sure I debugged the SimpleTypeModelBunder and verified the culture is passed properly to:
|
@frankabbruzzese you're correct this behaviour is intrinsic to MVC's use of
MVC can't stop using |
@dougbu , That said there seems to be just two options for the fallback, either calling parsing with adequate format string, or simply removing all thousands separators from the string and then trying again with the TypeConverter. |
Any updates on this? It's very easy to encounter this issue. Even using the |
@frankabbruzzese is correct options are limited here. Would take some reflection and a generic method to fall back to I recommend creating a MVC could create a handful of /cc @danroth27 @Eilon |
I wrote a custom SimpleTypeBinder and I followed the "remove separator " path. It is efficient and its impact is negligible as compared with the overall operations required by the binder. Yes, it accepts wrong inputs, substantially correcting th error, but ...in my opinion a cooperative error correcting behavior is a feature, not a problem. The TypeConverter approach appears too invasive to me since it would spread the effects of the problem all over the application ViewModels...like a virus. :) |
I like the idea "MVC could create a handful of TypeConverter..." . However, I would define an abstraction on top of TypeConverter.Something, like This way one might have a framework to customize string conversion of any type. |
That really is just |
@rynowak , not exactly, IModelBinder performs other tasks too (handling error in model state for instance), moreover each model binder needs the logics to select it. While, my idea was just abstracting type conversion from strings. However, I understand that, at least for what concerns simple types, IModelBinder is quite close to my abstraction, so that may be it is not worth to implements it: as a matter of fact, the SimpleTypeModelBinder is just a few lines of code around a TypeConverter. So what is an acceptable solution, simply the "remove separator" path? Forcing the user to specify a custom TypeConverter on each decimal property may be acceptable as a temporary patch, but not as a final solution. Frankly speaking, too invasive, for a temporary patch, too. |
It is worth out pointing out that maybe the problem is not just type conversion for decimals that is bugged. Maybe, using standard type converters for numbers is not a good idea since Html and JavaScript don't know anything about decimals, they know just about numbers. Thus, probably model binders should accept all number formats not just thousands separators for decimals. The only constraints being that the converted value is an acceptable value for the target type. Thus for instance a decimal should accept also an exponential notation if the number fits in the decimal representation (exactly as JavaScript would do), and an integer should accept also something like 1.00, but not 1.0.1. |
It seems reasonable for us to add a new model binder that is specific to float/double/decimal that allows the numerical separators. If anyone wants to go back to the "old" (1.x) behavior, they can remove this new model binder from the default list. This feature would be specific to the float/double/decimal types, and not apply to the various integer types. There are also no plans to build a new type conversion infrastructure here - just a simple fix. |
Wouldn't be better to use a type formatter instead of a type converter as outlined here?
|
@Eilon thousand separators for float/double/decimal is perfect. It is the same convention used by most of client side JavaScript number handling libraries. @wc-matteo the problem exists just for numbers, since dates work properly. There, is a conceptual bug in the way numbers are parsed: they need information on the format. On the contrary dates are able to parse any allowed format with no information on the format used. Moreover, also the default assumed for decimals is wrong, in that they assume an "N" format if no format indication is passed, and the "N" format doen't allow thousands separators while as a default decimals should allow the separator. The reason to use TypeConverter is that a TypeConverter may be created for any type, while not all types have a parse method. While there exists an IFormattable interface, an analogous interface for parsing do not exists. Thus, the only acceptable way to deal with all type that may be converted from string is the TypeFormatter. Moreover, since numbers come form Html/JavaScript that makes no difference between floats and decimals, thousands separator should be supported for any not integer type. This means, that also standard parser would fail. An ad hoc soulution is needed. |
Thanks @frankabbruzzese for the reasonable explanation. |
- #5502 - support thousands separators for `decimal`, `double` and `float` - add tests demonstrating thousands separators are not supported for numeric types - add tests demonstrating use of thousands separators with `enum` values
- #5502 - support thousands separators for `decimal`, `double` and `float` - add tests demonstrating `SimpleTypeModelBinder` does not support thousands separators for numeric types - add tests demonstrating use of commas (not thousands separators) with `enum` values
- #5502 - support thousands separators for `decimal`, `double` and `float` - add tests demonstrating `SimpleTypeModelBinder` does not support thousands separators for numeric types - add tests demonstrating use of commas (not thousands separators) with `enum` values
While client side validation hamdles properly decimals with thousands separators, model binder consider them invalid. So client validation submit the form, but then one gets a server side error.
This is an old problem (Mvc5, Mvc4...) and it is due to the ModelBinder using TypeDescriptor.GetConverter(type) to get a converter for strings to decimals. So the point is the "strange" behavior of the decimal TypeConverter.
Now it seems that the dotnet core team decided not to fix this behavior (I understand that this might cause unacceptable compatibilty issues).
So maybe the best place to fix this issue is the SimpleTypeModelBinder class, by using a different conversion method just for numbers.
It is worth pointing out that not only the jquery validation plugin, but substantially all client side globalization packages(like for instance both old and new version of the Globalize package) accept thousand separators when parsing/recognizing well formed numbers.
The text was updated successfully, but these errors were encountered: