ASP.NET MVC CRUD Validation

Posted by Ricardo Peres on ASP.net Weblogs See other posts from ASP.net Weblogs or by Ricardo Peres
Published on Wed, 30 May 2012 21:07:23 GMT Indexed on 2012/05/30 22:41 UTC
Read the original article Hit count: 543

One thing I didn’t refer on my previous post on ASP.NET MVC CRUD with AJAX was how to retrieve model validation information into the client.

We want to send any model validation errors to the client in the JSON object that contains the ProductId, RowVersion and Success properties, specifically, if there are any errors, we will add an extra Errors collection property. Here’s how:

   1: [HttpPost]
   2: [AjaxOnly]
   3: [Authorize]
   4: public JsonResult Edit(Product product)
   5: {
   6:     if (this.ModelState.IsValid == true)
   7:     {
   8:         using (ProductContext ctx = new ProductContext())
   9:         {
  10:             Boolean success = false;
  11:  
  12:             ctx.Entry(product).State = (product.ProductId == 0) ? EntityState.Added : EntityState.Modified;
  13:  
  14:             try
  15:             {
  16:                 success = (ctx.SaveChanges() == 1);
  17:             }
  18:             catch (DbUpdateConcurrencyException)
  19:             {
  20:                 ctx.Entry(product).Reload();
  21:             }
  22:  
  23:             return (this.Json(new { Success = success, ProductId = product.ProductId, RowVersion = Convert.ToBase64String(product.RowVersion) }));
  24:         }
  25:     }
  26:     else
  27:     {
  28:         Dictionary<String, String> errors = new Dictionary<String, String>();
  29:  
  30:         foreach (KeyValuePair<String, ModelState> keyValue in this.ModelState)
  31:         {
  32:             String key = keyValue.Key;
  33:             ModelState modelState = keyValue.Value;
  34:  
  35:             foreach (ModelError error in modelState.Errors)
  36:             {
  37:                 errors[key] = error.ErrorMessage;
  38:             }
  39:         }
  40:  
  41:         return (this.Json(new { Success = false, ProductId = 0, RowVersion = String.Empty, Errors = errors }));
  42:     }
  43: }

As for the view, we need to change slightly the onSuccess JavaScript handler on the Single view:

   1: function onSuccess(ctx)
   2: {
   3:     if (typeof (ctx.Success) != 'undefined')
   4:     {
   5:         $('input#ProductId').val(ctx.ProductId);
   6:         $('input#RowVersion').val(ctx.RowVersion);
   7:  
   8:         if (ctx.Success == false)
   9:         {
  10:             var errors = '';
  11:  
  12:             if (typeof (ctx.Errors) != 'undefined')
  13:             {
  14:                 for (var key in ctx.Errors)
  15:                 {
  16:                     errors += key + ': ' + ctx.Errors[key] + '\n';
  17:                 }
  18:  
  19:                 window.alert('An error occurred while updating the entity: the model contained the following errors.\n\n' + errors);
  20:             }
  21:             else
  22:             {
  23:                 window.alert('An error occurred while updating the entity: it may have been modified by third parties. Please try again.');
  24:             }
  25:         }
  26:         else
  27:         {
  28:             window.alert('Saved successfully');
  29:         }
  30:     }
  31:     else
  32:     {
  33:         if (window.confirm('Not logged in. Login now?') == true)
  34:         {
  35:             document.location.href = '<%
   1: : FormsAuthentication.LoginUrl 
%>?ReturnURL=' + document.location.pathname;
  36:         }
  37:     }
  38: }

The logic is as this:

  1. If the Edit action method is called for a new entity (the ProductId is 0) and it is valid, the entity is saved, and the JSON results contains a Success flag set to true, a ProductId property with the database-generated primary key and a RowVersion with the server-generated ROWVERSION;
  2. If the model is not valid, the JSON result will contain the Success flag set to false and the Errors collection populated with all the model validation errors;
  3. If the entity already exists in the database (ProductId not 0) and the model is valid, but the stored ROWVERSION is different that the one on the view, the result will set the Success property to false and will return the current (as loaded from the database) value of the ROWVERSION on the RowVersion property.

On a future post I will talk about the possibilities that exist for performing model validation, stay tuned!

© ASP.net Weblogs or respective owner

Related posts about .NET

Related posts about AJAX