Compartir en:

This post shows a way of using ASP.NET MVC Ajax Forms, and handling model errors using data annotations.

First of all, let’s start by listing the nuget packages you need to install:

  • jQuery.Validation
  • Microsoft.jQuery.Unobtrusive.Ajax
  • Microsoft.jQuery.Unobtrusive.Validation

Those packages will do the trick of taking the form data, post it via an Ajax requests and integrate nicely with ASP.NET MVC model errors.

In the View you should declare the form as follows:

@using(Ajax.BeginForm("AddPerson", new AjaxOptions
{
OnBegin = "onBegin(xhr)",
OnSuccess = "onSuccess(data, status, xhr)",
OnFailure = "onFailure(xhr, status, error)",
OnComplete = "onComplete(xhr, status)"
}))
{
	@Html.HiddenFor(x => x.Id)
	@Html.EditorFor(x => x.Name)
	@Html.ValidationMessageFor(x => x.Name)

	<button type="submit">Submit</button>
}

According to MSDN on AjaxOptions

OnBegin: Is the name of the JavaScript function to call immediately before the page is updated.

OnComplete:  Is the name of the function to call when response data has been instantiated but before the page is updated

OnSuccess: Is the name of the function that is called if the HTTP response is in the 200 range.

OnFailure: Is the name of the function that is called if the HTTP response is not in the 200 range.

What is kind of undocumented are the parameters that those callbacks receive, the most relevant are:

  • xhr:
    • responseJSON
    • responseText
    • status (Http Code: 200, 500, etc)
    • statusText
  • data: is the JSON representation of the object returned by the controller.

There is another property you should set if you want the form to update an element on the page with the response data automatically, it is UpdateTargetId which is the id of the Html element you want to get updated.

I don’t like the approach of letting the form auto update the element. It also has its drawbacks, like if you want to make a redirection after the response is returned, you can’t do that from the controller because you are in an Ajax call context. Instead, I’ve chosen to update the target with the server response manually. But to do that I had to serialize the view in a string property like this:


[HttpPost]
public ActionResult AddPerson(PersonModel model)
{
	if (ModelState.IsValid)
	{
		//Add Person.
	}

	return JsonView(ModelState.IsValid, "_AddPerson", model);
}

private JsonResult JsonView(bool success, string viewName, object model)
{
	return Json(new { Success = success, View = RenderPartialView(viewName, model) });
}

private string RenderPartialView(string partialViewName, object model)
{
	if (ControllerContext == null)
		return string.Empty;

	if (model == null)
		throw new ArgumentNullException("model");

	if (string.IsNullOrEmpty(partialViewName))
		throw new ArgumentNullException("partialViewName");

	ViewData.Model = model;

	using (var sw = new StringWriter())
	{
		var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, partialViewName);
		var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
		viewResult.View.Render(viewContext, sw);
		return sw.GetStringBuilder().ToString();
	}
}

This way I could update the target in the onSuccess callback or event do window.location.href with some url I return in the response and redirect to other page.

$("#ajaxFormContainer").html(data.View);

Model Errors

Additionaly, if there is any model error, the Html response will already contain those error descriptions. You only have to include the validation message in you view like we previously did.

You include error checks for your models by simple decorating your classes with Data Annotations, like this:


public class PersonModel
{
	public int Id { get; set; }

	[Required]
	public string Name { get; set; }
}

You can download the code sample here.

  • Hernan Veiras

    Software Developer

    I’ve been working as a Software Developer professionally for the last six years. During these years I gained experience developing enterprise oriented solutions such as intranets, portals and other web applications. Nowadays I’m looking forward to work more closely to research areas. In my spare time I like to travel, read and learn new stuff.

Dejar un comentario