How is formatted user input typically handled in an MVC application? A user entering "1,000.00" for a number for example. I'm somewhat surprised the default ModelBinder does not pick up on this. Would this be the type of thing I would create my own ModelBinder for?
I think that DefaultModelBinder use CultureInfo.CurrentCulture to parse numeric data.
Related
I create .NET WebApi project and I don't know how to localize standard model binder validations. For example, when I send invalid date time I got this:
Could not convert string to DateTime: 12vv.4. Path 'importDate', line
2, position 24.
It's not a friendly message for the end user. Is there any possible how to localize validations? Or another way?
Thank you
My input is an annoying free text in which I need to extract the date. This date could be present in any of the formats with anomalies.
eg. This is 9.9.12 date
This is 9912 date
This is 0992012 date
Any possible format.
dMy
ddMMyy
ddMMyyyy
Mdyy etc..
I am able to validate if the text is in date format for ddMMy* but not any other. I was looking into this https://www.c-sharpcorner.com/blogs/date-and-time-format-in-c-sharp-programming1 link to see what other formats could be possible but I got no leads.
Is this correct to write like in the following method for a date format say - 9912?
Date.ParseExact(test.ToString,"dMy", Globalization.CultureInfo.InvariantCulture)
If yes, the system is populating me the following err:
System.FormatException: String was not recognized as a valid DateTime.
Can anyone please share a reliable approach to tackle such problems?
There is no single way to accomplish what you're trying to do. Specifically, because the intent is so broad, it becomes hard to infer what the user actually means (e.g. how do you differentiate month vs. day).
Depending on how you're implementing your application, you need to implement input validation.
For a console app, I can envision you using something like:
if (DateTime.TryParse(line, out value))
{
// Parse-able date.
}
else
{
// Non-parseable date.
}
If you're building a WPF application, you can use binding validation. If you're building an ASP.NET MVC application, you can also implement model validation. Your mileage may vary - you should definitely consider constraining what your users can feed the application.
I have an MVC Web-API application for inner use. I have some pages with forms and numeric fields. I need to install this on a German computer, and the users will be only Germans. In Germany they write "3,5" instead of "3.5" (with a comma).
In IIS configuration the culture is "Invariant culture" and since the computer is German - the localize is "de-DE".
When the users write "3,5" in the field - I can see in firebug that "3,5" is what is sent in JSON, but the server gets it as "35".
Can I handle it on server-side? (I don't want to change the json because I'll need to do it in every field and page)
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class ItemsController : ApiController, IDisposable
{
[Authorize(Roles = "Admin")]
[HttpPost]
public HttpResponseMessage UpdateItem(ItemViewModel itemVM)
{
// JSON data sent data.NumProp1 = "3,5"
// itemVM.NumProp1 contains "35" instead of "3.5"
}
}
You should not localize your JSON - see http://www.json.org for the spec (which only shows the dot as a separator) and How to localize when JSON-serializing? for a similar question.
I wouldn't recommend trying to read your customized JSON - it may sound like a quick win right now, but in the end you simply aren't using JSON.
You must use CultureInfo.InvariantCulture on all your string formating calls when handling persitence (and JSON exchanges are technically a form of persitence):
Persisting Data
The InvariantCulture property can be used to persist data in a
culture-independent format. This provides a known format that does not
change and that can be used to serialize and deserialize data across
cultures. After the data is deserialized, it can be formatted
appropriately based on the cultural conventions of the current user.
For example, if you choose to persist date and time data in string
form, you can pass the InvariantCulture object to the
DateTime.ToString(String, IFormatProvider) or
DateTimeOffset.ToString(IFormatProvider) method to create the string,
and you can pass the InvariantCulture object to the
DateTime.Parse(String, IFormatProvider) or
DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) method
to convert the string back to a date and time value. This technique
ensures that the underlying date and time values do not change when
the data is read or written by users from different cultures.
This applies to all types: numerics, decimals, floats and doubles, date and time etc. Use the invariant culture both when writing and when reading serialized data. Use invariant culture on both sides of a JSON exchange.
BTW, if you'd use the built-in JSON serializers, you'd already get this lunch for free: JsonWriter.cs, JsonReader.cs.
As already said: JSON is a standard, and you should never deviate from the standard. Doing that will make your life miserable.
If the users enter some numbers in a web form, that web form should serialize that in the correct JSON format. I think usually that is done already, if you use the right numeric types in your form, like input type='number', etc. On the server end, you should read it using the InvariantCulture.
This need for a general solution is acknowledged by the W3C, as you can see in the draft W3C HTML JSON form submission.
In addition to the other answers, if you want to just replace the German "," decimal separator with the current culture one, which makes the conversion parse correctly, use:
str = str.Replace(",", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
You can then convert your string into a numeric value using stuff like Convert.ToInt32
In my MVC app, I made this simple test function...
Function test(d As Decimal) As JsonResult
Return Json(d)
End Function
Sending .../?d=1900 works fine.
Sending .../?d=1,900 fails with "d" being null.
Sending .../?d=1.900 converts d to 1.9D <--- I NEED THIS ONE
Since I'm danish, I want to be able to pass 1.900 to "d" so it will be one-thousand-nine-hundred.
I tried setting this in web.config...
...that din't help.
Any idea?
What you need to be doing here is doing a culture-specific conversion to decimal. If you don't specify a culture, ASP.NET MVC will use the Invariant Culture. Similarly, if you use the decimal.Parse function without a culture will use the system's current culture.
What you need to do is use the function Decimal.Parse with a culture that you supply. see here
You could set each user's culture up in whatever user/session sort of setup you have, or you could pass it in as a parameter. E.g:
/?d=1,900&culture=da-DK
Then you might pass
decimal.Parse(d, System.Globalization.CultureInfo.GetCultureInfo(culture))
I have an ajax calendar control that I specified the date format to be yyyy-MM-dd. Is it possible to have the comparevalidator validate that type of date sepcifically and have it fail for everything else? right now it seems to only take dd-MM-yyyy.
Thanks.
I assume validators use the current CultureInfo object to determine the date format.
CultureInfo.DateTimeInfo.ShortDatePattern
Try changing the page culture(MSDN).
If you don't want to go that route you can always create a custom validator.
Set CultureInvariantValues="true"
from the docs:
Culture Invariant Values - When doing
conversion on a compare validator's
non strongly-typed properties
(CompareValidator.ValueToCompare,
RangeValidator.MaximumValue,
RangeValidator.MinimumValue) the
validator will use a culture neutral
format (Date: YYYY/MM/DD, Double &
Currency: US culture format) to do the
conversion when CultureInvariantValues
is true.
EDIT
Searching on the web, I found a similar question in another forum, see:
http://forums.asp.net/t/1229615.aspx, maybe the last answer (that was gave by Mohan.Raju) can solve your problem too.