I am using Entity Framework with partial classes added on so I can use DataAnnotation attributes. Does anyone know how to add a data annotatin which will verify that a field is a whole number (or a DataType of int or long)? I'm surprised there is no [DataType(DataType.Integer)]
attribute. I tried to create a custom attribute, but it doesn't work because the value it receives is always null:
[DataTypeWholeNumberAttribute(ErrorMessage = "Zip must be a whole number")]
public object Zip{ get; set; }
public class DataTypeWholeNumberAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
long i;
if (value == null) //value is always null.
return false;
return Int64.TryParse(value.ToString(), out i);
}
}
Obviously I'm missing the point, but I don't know enough to know what I'm missing. Can anyone shed some light?
Well I figured out part of it. My problem is the field is an integer in the model. Regardless of what validatior I add, the binding will detect that the value isn't an integer, remove the value, and return the detault message (e.g. "value is not valid
for this field"). Then, when my validator fires, the value is always null. If I try this same thing on a string field, it works fine. The existing Range attribute has the same problem. If the value is text (or a decimal), the default DataType message will
be returned before it has a chance to evaluage the Range.
So now that I know what the problem is, is there an easy way to get around it (without changing all my fields to strings)?
While the default behavior will prevent non-integers from being submitted (adding the [Required] will also deal with nulls), am I correct in assuming that your issue is that you need to only customize the message being returned if the value is not an integer?
You can put a small amount of logic into your Controller that will override the default behavior on the server-side regardless of Data-type errors, and will add the string you'd like.
public ActionResult CreateAddress (testModel addr)
{
if (!ModelState.IsValidField("Zip"))
{
ModelState.Remove("Zip");
ModelState.AddModelError("Zip", "Zip must be a whole number.");
}
if(!ModelState.IsValid)
return View(addr);
return RedirectToAction("Index");
}
Interesting. However, it seems to be doing the same thing. When it hits IsValidForField, the value has already been ruled invalid and removed (the field is null). The default message is displayed.
[HttpPost]
public ActionResult Edit(string PreviousButton, string NextButton, NamedInsuredViewModel viewModel)
{
try
{
if (!ModelState.IsValidField("Zip")) //Zip is already null.
{
ModelState.Remove("Zip");
ModelState.AddModelError("Zip", "Zip code must be a whole number");
}
if (ModelState.IsValid)...
Try that again removing your custom validation attribute.
Also, are you calling ValidateModel, TryValidateModel, UpdateModel, or TryUpdateModel
after that code?
The code snippet I provided must be run AFTER those calls, as they all clear the ModelState dictionary and replace it with the results from model binding.
jstrope
Member
46 Points
42 Posts
Using DataAnnotations to verify integer
Sep 30, 2010 07:02 PM|LINK
I am using Entity Framework with partial classes added on so I can use DataAnnotation attributes. Does anyone know how to add a data annotatin which will verify that a field is a whole number (or a DataType of int or long)? I'm surprised there is no [DataType(DataType.Integer)] attribute. I tried to create a custom attribute, but it doesn't work because the value it receives is always null:
[DataTypeWholeNumberAttribute(ErrorMessage = "Zip must be a whole number")]
public object Zip{ get; set; }
public class DataTypeWholeNumberAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
long i;
if (value == null) //value is always null.
return false;
return Int64.TryParse(value.ToString(), out i);
}
}
Obviously I'm missing the point, but I don't know enough to know what I'm missing. Can anyone shed some light?
DataAnnotations mvc2 Attributes
jstrope
Member
46 Points
42 Posts
Re: Using DataAnnotations to verify integer
Sep 30, 2010 08:07 PM|LINK
Well I figured out part of it. My problem is the field is an integer in the model. Regardless of what validatior I add, the binding will detect that the value isn't an integer, remove the value, and return the detault message (e.g. "value is not valid for this field"). Then, when my validator fires, the value is always null. If I try this same thing on a string field, it works fine. The existing Range attribute has the same problem. If the value is text (or a decimal), the default DataType message will be returned before it has a chance to evaluage the Range.
So now that I know what the problem is, is there an easy way to get around it (without changing all my fields to strings)?
jamesqua
Star
8305 Points
1430 Posts
Re: Using DataAnnotations to verify integer
Sep 30, 2010 08:13 PM|LINK
I think what you are looking for is the RegularExpression data annotation. Try this
[RegularExpression("[0-9]{1,}")]jamesqua
Star
8305 Points
1430 Posts
Re: Using DataAnnotations to verify integer
Sep 30, 2010 08:26 PM|LINK
OK, it looks like the security filter didn't like what I just wrote. Just search on the internet for regular expression data annotation.
jstrope
Member
46 Points
42 Posts
Re: Using DataAnnotations to verify integer
Oct 01, 2010 11:41 AM|LINK
I tried that (here's a link for others: http://blogs.x2line.com/al/articles/965.aspx) but it has the same problem. The value is removed before my validator gets to it.
RDeFreitas
Member
148 Points
27 Posts
Re: Using DataAnnotations to verify integer
Oct 01, 2010 04:20 PM|LINK
While the default behavior will prevent non-integers from being submitted (adding the [Required] will also deal with nulls), am I correct in assuming that your issue is that you need to only customize the message being returned if the value is not an integer?
MVC Gaming and Social Networking Application DevBlog
Did my response solve your issue? Please Mark as Answer.
jstrope
Member
46 Points
42 Posts
Re: Using DataAnnotations to verify integer
Oct 01, 2010 04:24 PM|LINK
Yes, RDeFreitas.
RDeFreitas
Member
148 Points
27 Posts
Re: Using DataAnnotations to verify integer
Oct 01, 2010 04:34 PM|LINK
You can put a small amount of logic into your Controller that will override the default behavior on the server-side regardless of Data-type errors, and will add the string you'd like.
public ActionResult CreateAddress (testModel addr) { if (!ModelState.IsValidField("Zip")) { ModelState.Remove("Zip"); ModelState.AddModelError("Zip", "Zip must be a whole number."); } if(!ModelState.IsValid) return View(addr); return RedirectToAction("Index"); }MVC Gaming and Social Networking Application DevBlog
Did my response solve your issue? Please Mark as Answer.
jstrope
Member
46 Points
42 Posts
Re: Using DataAnnotations to verify integer
Oct 01, 2010 04:50 PM|LINK
Interesting. However, it seems to be doing the same thing. When it hits IsValidForField, the value has already been ruled invalid and removed (the field is null). The default message is displayed.
[HttpPost] public ActionResult Edit(string PreviousButton, string NextButton, NamedInsuredViewModel viewModel) { try { if (!ModelState.IsValidField("Zip")) //Zip is already null. { ModelState.Remove("Zip"); ModelState.AddModelError("Zip", "Zip code must be a whole number"); } if (ModelState.IsValid)...RDeFreitas
Member
148 Points
27 Posts
Re: Using DataAnnotations to verify integer
Oct 01, 2010 05:06 PM|LINK
Try that again removing your custom validation attribute.
Also, are you calling ValidateModel, TryValidateModel, UpdateModel, or TryUpdateModel after that code?
The code snippet I provided must be run AFTER those calls, as they all clear the ModelState dictionary and replace it with the results from model binding.
MVC Gaming and Social Networking Application DevBlog
Did my response solve your issue? Please Mark as Answer.