Data Annotation - wrong error message for numbers - c#

I have a double variable :
public double Width { set; get; }
I want to validate the number and display an error message so I added:
[Range(0.0, Double.MaxValue, ErrorMessage = "Width must be a valid number")]
It works great if I enter a negative number, but if I leave it empty or enter letters - the inner error message is
"Input string was not in a correct format."
I'm not usign #html.validationmessagefor , because I need to handle the ModelState's ErrorMessage or error.exception.InnerException.message manually.
How can I fix that?

it seems that this error message comes from a double.Parse
the Data Annotation attributes are not used by the double class, they are just used by some frameworks.
anyway it looks like your input string was no valid double, so a range validation has nothing to do with a valid double string.

Related

Input string 'x' is not a valid number error with JsonConvertDeserializeObject

I have a string for billingpostalcode. When you enter pure numbers on it ex: '12345' then it is working fine. But for example you put '123aa' or 'abcde' it is producing an exception. It is a string and not an integer so i don't understand the error.
{"Unexpected character encountered while parsing number: s. Path 'billingPostalCode', line 1, position 119."}
string billingPostal = billingPostalCode;
var obj = JsonConvert.DeserializeObject($"{{ 'odrDetailHdr' : {orderDetailHeaderJson}, 'billingPostalCode' : {billingPostal}, 'odrProductList': {orderTrackingDetailsProductJson}, 'odrDetailOtherHdr': {orderDetailOtherHeaderJson} }}");
Anyone has an idea why?
There is different notation between a string and a number in the json format.
"employee":{ "name":"John", "age":30, "city":"New York" }
Notice the difference between the string "name":"John"and the number "age":30, They are not interchangeable
However, in your example you could add the quotes, or use a converter via an attribute when using json.net

Regex for 4 digits including 0 at first position not working right

I need a regex which allows only 4 digits and those four can contain 0 at any position.
Below is my code:
View :
<label asp-for="UserId"></label><br />
<input asp-for="UserId" class="form-control" maxlength="4" />
<span asp-validation-for="UserId" class="text-danger"></span>
Model :
[RegularExpression(#"^([0-9]{4})$", ErrorMessage = "Please enter last 4 digits of your user Id.")]
[Display(Name = "Last 4 digits of user Id")]
public int? UserId{ get; set; }
But if I type in 0645, it throws an error "Please enter last 4 digits of your user Id.".If I change it to say 4567, it works fine. So how should I fix my regex?
You do not have any problem with your regex. As was already said in the comments, your property is an integer and when you set its value to 0645 internally it is converted to int and become 645.
If you look into RegularExpressionAttibute class, line 59, on GitHub you will realize that the method IsValid receives and object and then parses it as a string.
So lets look at the complete flow of your data.
1) Your user types a value into a textbox. ("0645")
2) ModelBinder converts the string typed into an integer. (645)
3) Inside RegularExpressionAttibute.IsValid your integer is converted again into an string ("645")
4) Regular Expression is applied to the value ("645") not ("0645"). So it will not pass your validation.
This is the RegularExpressionAttibute.IsValid method.
override bool IsValid(object value) {
this.SetupRegex();
// Convert the value to a string
string stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);
// Automatically pass if value is null or empty. RequiredAttribute should be used to assert a value is not empty.
if (String.IsNullOrEmpty(stringValue)) {
return true;
}
Match m = this.Regex.Match(stringValue);
// We are looking for an exact match, not just a search hit. This matches what
// the RegularExpressionValidator control does
return (m.Success && m.Index == 0 && m.Length == stringValue.Length);
}
Whats the solution / suggestion?
You are expecting 4 digits as an input, and until now you don't said anything about have to do any kind of calculation with this.
As you don't need to do any calculation you can keep it as an string without any harm. Just keep validating that your string contains 4 digits (you are already doing it).
And if you need to do any calc in the future just convert the string to integer when its needed.
So just change this line:
public int? UserId{ get; set; }
To this:
public string UserId{ get; set; }

leading zero dynamically gets removed

I have strange validation error
public long mobile { get; set; }
[RegularExpression(#"^([09]{2}[0-9]{8})$", ErrorMessage = "mobile number is not correct")]
if the user entered 094532415678 it is correct but validation error appears due to the dynamic removal of leading zeroes in asp c# , model will receive the above number as 94532415678 and wont be saved to database throwing error for mobile validation
I have tried to save it to string and add the leading zero to mobile and save it but still when the string gets converted to "long" directly it removes the leading zero , any solution for this problem
Store telephone numbers (and simular information) as a string. Leading 0's are removed when you save phonenumbers as a number (long).
try
[RegularExpression(#"^([09]{2}[0-9]{8})$", ErrorMessage = "mobile number is not correct")]
public string mobile { get; set; }

How to properly validate a price/currency field?

How can I properly validate a price field when doing postback?
I have already checked: How can I validate a currency field? but that doesn't fulfil my expectations.
I've tried with (and some variations):
[Range(0, (double)decimal.MaxValue)]
[DataType(DataType.Currency, ErrorMessage = "...")]
public decimal? Price {get; set;}
Problems:
It never uses the [DataType...] attribute to perform validations.
When the value used is not of decimal type, the issued validation error will be a standard English message that I don't know how to customize and need to.
If I make it string instead of decimal?, then the range validation will be thrown for non-decimal or negative values, but it will still allow values like: 1.23456, which is not the currency format I'm expecting.
I'm looking for a built-in approach before I have to create my own custom validation or regular expression. Something like:
[EmailAddress()]
public string ContactEmail {get; set; }
This perfectly suits me!
You can use FluentValidation. You create your own validator class inheriting from : AbstractValidator and inside the constructor you can put all your logic.
MyCurrencyValidatorMyClass : AbstractValidator<MyClass>
{
MyCurrencyValidatorMyClass()
{
RuleFor(x => x.MyField).NotNull().GreatherThan(0);
//All your rules
}
}
var validator = new MyCurrencyValidatorMyClass();
var myClassVar = new MyClass();
validator.Validate(myClassVar);
Also you can integrate your validator with MVC, for reference please see
https://fluentvalidation.codeplex.com/wikipage?title=mvc
For decimal reference see
https://github.com/JeremySkinner/FluentValidation/blob/master/src/FluentValidation/Validators/ScalePrecisionValidator.cs
This is the nuget package https://www.nuget.org/packages/FluentValidation
You can try this RegEx on your Price model property. It will check for strings in the format of "XXXX.XX" where X is a numeric digit (0-9):
[RegularExpression(#"\d{1,20}(\.\d{1,2})?", ErrorMessage = "Invalid Price. Please use the format of XXXX.XX.")]
The first range d{1, 20} allows up to twenty digits before the decimal place. The second range d{1, 2} allows up to two decimal places.

STRING: how to get string output from this input string?

How do you get the message from the following inputs
Input is formated by field name separated by comma, followed by a colon, space and then the error message.
<FieldName1>, <FieldName2>, <FieldName3>: <ErrorMessage>"
Input Example
"ConsumerSecret, ConsumerKey: Invalid application credentials"
"Password: Invalid Must contain at least one alpha, one numeric, and one special character"
Method
string Message GetErrorByField (string FieldName, string InputString);
1
ErrorMessage = GetErrorByField("ConsumerSecret", "ConsumerSecret, ConsumerKey: Invalid application credentials");
ErrorMessage should now equal
"Invalid application credentials".
2
ErrorMessage = GetErrorByField("ConsumerKey", "ConsumerSecret, ConsumerKey: Invalid application credentials");
ErrorMessage should now equal
"Invalid application credentials".
3
ErrorMessage = GetErrorByField("Password", "Password: Invalid Must contain at least one alpha, one numeric, and one special character");
ErrorMessage should now equal
"Invalid Must contain at least one alpha, one numeric, and one special character".
Split the InputString i.e., second parameter in GetErrorByField() method by : then you will get the result by considering the splitted string with index 1
string Message = InputString.Split(':')[1].Trim();
You can simply use the Split method of the string class, and get the appropriate value:
GetErrorByField(string str)
{
var splited = str.Split(":".ToCharArray());
if (splited != null && splited.Length == 2)
return splited[1].TrimStart().TrimEnd();
return string.Empty;
}

Categories

Resources