Integer check against optional attributes in MVC

I am trying to test a property on a model that I have. This property is NOT required, therefore, if its invalid MVC seems to ignore it. I even created a custom ValidationAttribute, but nothing works.

public class NumberWang : ValidationAttribute { public override bool IsValid(object value) { if (value == null) return true; int g; if (int.TryParse(value.ToString(), out g)) { if (g >= 0) return true; } return false; } } public class MyModel { [Range(0, 999999, ErrorMessage = "category_id must be a valid number")] [NumberWang(ErrorMessage = "That NumberWang!")] public int? category_id { get; set; } /* there are other properties of course, but I've omitted them for simplicity */ public void Validate() { Validator.TryValidateProperty(this.category_id, new ValidationContext(this, null, null) { MemberName = "category_id" }, this.validation_results); } } 

If I pass the value 'abc' as category_id for this model, it only checks the penalty. What am I doing wrong?

+4
source share
4 answers

I found an ugly workaround.

It seems that if category_id is a null int? value int? , and my value is not a valid number, an empty value is passed, and the model does not see the invalid value "abc".

 [Range(0, 999999, ErrorMessage = "category_id must be a valid number")] public int? category_id { get; set; } // when we pass a good number MyAction?category_id=123 validation: successful // when we pass a bad number // validation ignores it. not what we want. MyAction?category_id=abc validation: successful 

If I change category_id to a non-nullable int , it will not check even when the value is not passed.

 [Range(0, 999999, ErrorMessage = "category_id must be a valid number")] public int? category_id { get; set; } // when we pass a good number MyAction?category_id=123 validation: successful // when we pass an bad number MyAction?category_id=abc validation: "category_id must be a valid number" // BUT, when we don't pass any number at all ... MyAction validation: "category_id must be a valid number" 

Ugly workaround

If I changed category_id to string and then only converted it to int , when I need it, I can check it correctly using only [Range]

 [Range(0, 999999, ErrorMessage = "category_id must be a valid number")] public string category_id { get; set; } // when we pass a good number MyAction?category_id=123 validation: successful // when we pass a bad number MyAction?category_id=abc validation: "category_id must be a valid number" // no number, no validation. hooray! MyAction validation: successful 

This is ugly, but it works.

(Note: a custom attribute is not needed, so I deleted it and just used [Range])

+3
source

Model:

 // "(\s*[0-9]{0,6})" for 999999 max // "(\s*[0-9]*)" for "infinite" [RegularExpression(@"(\s*[0-9]{0,6})", ErrorMessage = "Field must be a natural number (max 999999)")] public int? Quantity { get; set; } 

View:

 @Html.TextBoxFor(m => m.Quantity) @Html.ValidationMessageFor(m => m.Quantity) 
+1
source

Your model must first implement an IValidatableObject, but the Validate method will only be called if the ModelState is valid. This link may help . Do you get your model as a parameter in action? Are you requesting ModelState.IsValid? This should work fine with the default model binding.

0
source

I found a workaround that I like. The problem I ran into was a similar problem when the value was supposed to be greater than 0 and a number, so as soon as I tried to add a 9999999999 (invalid) string as a number, it threw an exception and did not show that the state model has a message about error in the message. I hope this is relevant, as it sounds like this: "The rules do not seem to apply correctly when I print the wrong number"

Since my number must be positive, I intercepted the value into an anonymous type object (dynamic) and used it as an intercepting body between the user of the model and the private property int. When I did this, the data annotations worked as expected.

  public dynamic MyProperty { get { return _myProperty; } set { try { 

/ I need to convert the value to String, because it comes as String [], and if there is more than one value, then this should be problematic, so you attach it with an invalid character and throw an error or you take the first value / _myProperty = = Convert.ToInt32 (String.Join ("a", value)); } catch (exception e) {_myProperty = -1; }}}

  private int _myProperty; 
0
source

Source: https://habr.com/ru/post/1497987/


All Articles