I want to put a rule between two properties that is one property have to be greater than the other. So what is the data validation attribute that can let me do this ?
Here are my properties
public int Min{get;set;}
public int Max{get;set;}
As you can easily understand Max have to be greater than Min.
Thank you for your help!
ComponentModel. DataAnnotations namespace includes the following validator attributes: Range – Enables you to validate whether the value of a property falls between a specified range of values. RegularExpression – Enables you to validate whether the value of a property matches a specified regular expression pattern.
In ASP.NET MVC, Data Annotation is used for data validation for developing web-based applications. We can quickly apply validation with the help of data annotation attribute classes over model classes.
Data validations on your object strike me as a good thing (as well as using client side validation).
This is an attribute that you can use to do what you are asking (which will be able to compare pairs of types that implement IComparable)
public class GreaterThanAttribute : ValidationAttribute
{
public GreaterThanAttribute(string otherProperty)
: base("{0} must be greater than {1}")
{
OtherProperty = otherProperty;
}
public string OtherProperty { get; set; }
public string FormatErrorMessage(string name, string otherName)
{
return string.Format(ErrorMessageString, name, otherName);
}
protected override ValidationResult
IsValid(object firstValue, ValidationContext validationContext)
{
var firstComparable = firstValue as IComparable;
var secondComparable = GetSecondComparable(validationContext);
if (firstComparable != null && secondComparable != null)
{
if (firstComparable.CompareTo(secondComparable) < 1)
{
object obj = validationContext.ObjectInstance;
var thing = obj.GetType().GetProperty(OtherProperty);
var displayName = (DisplayAttribute)Attribute.GetCustomAttribute(thing, typeof(DisplayAttribute));
return new ValidationResult(
FormatErrorMessage(validationContext.DisplayName, displayName.GetName()));
}
}
return ValidationResult.Success;
}
protected IComparable GetSecondComparable(
ValidationContext validationContext)
{
var propertyInfo = validationContext
.ObjectType
.GetProperty(OtherProperty);
if (propertyInfo != null)
{
var secondValue = propertyInfo.GetValue(
validationContext.ObjectInstance, null);
return secondValue as IComparable;
}
return null;
}
}
You can then decorate your model:
public int Min{get;set;}
[GreaterThan("Min")]
public int Max{get;set;}
This is a useful question regarding less than validations MVC custom validation: compare two dates but applies to dates rather than integers but the same approach applies
You could use a Attribute or your view model could implement IValidatableObject. What's nice is that the asp.net mvc modelbinder will automatically run this on post.
public class TestCompareModel : IValidatableObject
{
[Required]
public Int32 Low { get; set; }
[Required]
public Int32 High { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (High < Low)
results.Add(new ValidationResult("High cannot be less than low"));
return results;
}
}
Controller action:
[HttpPost]
public ActionResult Test(TestCompareModel viewModel)
{
if (!ModelState.IsValid)
return View(viewModel);
return RedirectToAction("Index");
}
View
@model Scratch.Web.Models.TestCompareModel
@{
ViewBag.Title = "Test";
}
<h2>Test</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TestCompareModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Low, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Low, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Low, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.High, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.High, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.High, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
I agree with Exception, JQuery is much easier to work with than the model itself for accomplishing this kind of functionality. However that being said with no experience in Javascript/Jquery its worth having a look at the documentation for JQuery here.
You will also find great tutorials here
And the most important part, the actual JQuery library file here. You can download the file and include it in your solution OR simply include a link to a server hosted CDN version of the file in the header of your view. (both options have instructions provided on the link I gave you)
An update to Exceptions answer however, you do not include the functionality required to only allow integer values in the input controls. To fix this simply change the inputs type attribute to "number" like this.
<input type="number" id="Max" name="Max" />
And modify the Script to remove parsing of String to Integer like this:
$("#Max").focusout(function(){
if( $(this).val() < $("#Min").val() )
{
$("#errormess").html('Max value cannot be lower then min Value');
}
else{ $("#errormess").html(''); }
});
$("#Min").focusout(function(){
if( $(this).val() >= $("#Max").val() )
{
$("#errormess").html('Max value cannot be lower then min Value');
}
else{ $("#errormess").html(''); }
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With