First of all thanks a lot to everyone who is answering the questions here. I a new learner of asp framework and has learned a lot from these answers.
I a model with 2 columns
[Required]
public string person1 { get; set; }
[Display(Name = "Service")]
[MaxLength(50)]
[RequiredIf("person1 ", "Yes", ErrorMessage = "Service Field is Required")]
public string Service { get;set; }
and then i have used RequiredIf from this website.
public class RequiredIfAttribute : ValidationAttribute
{
private RequiredAttribute innerAttribute = new RequiredAttribute();
public string DependentUpon { get; set; }
public object Value { get; set; }
public RequiredIfAttribute(string dependentUpon, object value)
{
this.DependentUpon = dependentUpon;
this.Value = value;
}
public RequiredIfAttribute(string dependentUpon)
{
this.DependentUpon = dependentUpon;
this.Value = null;
}
public override bool IsValid(object value)
{
return innerAttribute.IsValid(value);
}
}
public class RequiredIfValidator : DataAnnotationsModelValidator<RequiredIfAttribute>
{
public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute)
: base(metadata, context, attribute)
{ }
public override IEnumerable<ModelValidationResult> Validate(object container)
{
var field = Metadata.ContainerType.GetProperty(Attribute.DependentUpon);
if (field != null)
{
var value = field.GetValue(container, null);
if ((value != null && Attribute.Value == null) || (value != null && value.Equals(Attribute.Value)))
{
if (!Attribute.IsValid(Metadata.Model))
yield return new ModelValidationResult { Message = ErrorMessage };
}
}
}
}
Controller has following action method which is being executed everytime i click on save button on screen:-
public ActionResult Create( Person person1)
{
if (ModelState.IsValid)
{
db.Person.Add(person1);
try
{
db.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
return RedirectToAction("Index");
}
return View(person);
}
Following is create view
<div class="form-group">
@Html.LabelFor(model => model.person1 , htmlAttributes: new { @class = "control-label col-md-4" })
<div class="col-md-4">
@Html.RadioButtonFor(model => model.person1 , "Yes", new { id = "person1Yes" })
@Html.Label("Yes", "Yes")
@Html.RadioButtonFor(model => model.person1 , "No", new { id = "person1No" })
@Html.Label("No", "No")
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Service, htmlAttributes: new { @class = "control-label col-md-4" })
<div class="col-md-4">
@Html.EditorFor(model => model.Service, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Service, "", new { @class = "text-danger" })
</div>
</div>
So following this are happening when i click on create button:-
1.if person1 has value "Yes" selected,i get warning on screen that Service is madatory. 2. In case of No,it does not show any warning.
But when i select "NO" and click save. It fails at db.savechanges() with following error "Service Field is Required". I not sure why it is working on client side but failing while save.
I have tried to explain as much as possible for a novice me. I could have used wrong terminologies,apologies.
That is because the validation fired at the browser level (Javascript validation) sees that when No is selected, it passes validation. However, on the server side EF is enforcing the same validations. Check and see what the value of person1 is on the server side before saving it: If it is empty or yes, then that is the problem.
In situations like this, I create one model for my view (the one you have) and one model for my ORM (EF). In the EF model, do not put the RequiredIf attribute. Before saving convert the model (for the view) to the model (for EF) and all should be good.