Monday, November 14, 2011

How to render Model validation errors on Ajax Calls in ASP.NET MVC

As we all know that Web Development without Jquery & Ajax is an impractical idea. Most of us use Data Annotations for validation purposes. How these Data Annotatation will work on client side when you have Ajax calls in your application. MVC doesn't take care of firing these validations when Ajax calls are made. The below approach can help you handle this situation.

1. MVC generates a spantag i.e. span class="data-valmsg-for=Field Name" for each field that has Html.ValidationMessageFor() in it's markup.
2. Let controller action validates the model and returns you a Json object with all validation messages back to your Ajax call. This collection will have both the Key i.e. Field Name and the validation message.
3. The Ajax call will loop thru this Array and render this messages in the span of appropriate field element.

Base Controller Code


public JsonResult ValidateModel(string status = "")
{
bool isValid = ModelState.IsValid;

return Json(new
{
Valid = isValid,
NewId = 0,
Errors = GetErrorsFromModelState(),
Status = !string.IsNullOrWhiteSpace(status) ?
status :
isValid ? "Success" : "Failure"
});
}

public Dictionary GetErrorsFromModelState()
{
var errors = new Dictionary();

foreach (var key in ModelState.Keys)
{
// Only send the errors to the client.
if (ModelState[key].Errors.Count > 0)
{
errors[key] = ModelState[key].Errors;
}
}

return errors;
}

public void ClearValidationError()
{
foreach (var key in ModelState.Keys)
{
if (ModelState[key].Errors.Count > 0)
{
ModelState[key].Errors.Clear();
}
}
}


Application Contoller Code

public ActionResult Edit(TemplateViewModel model)
{
bool returnStatus = false;
var id = SaveNewTemplate(model);
returnStatus = true;
JsonResult validation = ValidateModel();
return Json(new { success = returnStatus, id = id, message = message, Validation = validation });
}


Cliend side code

$.ajax({
type: "POST",
url: form.attr("action"),
dataType: "json",
async: false,
cache: false,
data: form.serialize(),
success: function (result) {
if (result.success) {
if (result.Validation != null && !result.Validation.Data.Valid) {
$.each(result.Validation.Data.Errors, function (key, value) {
if (value != null) {
var container = $('span[data-valmsg-for="' + key + '"]');
container.removeClass("field-validation-valid").addClass("field-validation-error");
container.html(value[value.length - 1].ErrorMessage);
}
});
}
}
});

3 comments:

  1. Hi, I am obtaning error in lines 04 and 05 of Application Controller Code.
    SaveNewTemplate and message variable not found.

    Thanks

    ReplyDelete