2011-01-14 25 views
20

He estado jugando con el nuevo MVC3 Json Model Binding y es bastante agradable.ASP.Net MVC 3 Modelo JSON Enlace y validación del modelo del lado del servidor mezclado con la validación del lado del cliente

Actualmente, puedo publicar JSON en el controlador y vincularlo. La validación del modelo también ocurre muy bien.

Pero, ¿qué ocurre si el modelo no es válido?

me gustaría volver JSON y tener el lado del cliente notificar al usuario (lo mismo que para realizar la validación del lado del cliente normal en la MVC)

¿alguien sabe de algunos tutoriales sobre cómo realizar esto?

¿Esto es posible?

¿O hay marcos que pueda aprovechar para hacer esto?

+0

¿Cómo estás publicando este JSON? ¿Estás usando AJAX? –

+0

sí, publicando a través de ajax –

+0

@TheCodeKing ¿Vuelve a esta pregunta? –

Respuesta

25

El siguiente ejemplo funciona para mí cuando se utiliza JavaScript discreto en MVC3. Estoy haciendo algo muy similar. Dada la siguiente JsonResponse clase:

public enum Status 
{ 
    Ok, 
    Error 
} 

public class JsonResponse 
{ 
    public Status Status { get; set; } 
    public string Message { get; set; } 
    public List<string> Errors { get; set; } 
} 

Mi controlador puede tener un método así:

[HttpPost] 
public ActionResult Login(UserLoginModel model) 
{ 
    JsonResponse res = new JsonResponse(); 

    if (!ModelState.IsValid) 
    { 
     res.Status = Status.Error; 
     res.Errors = GetModelStateErrorsAsString(this.ModelState); 
     res.Message = "Oh dear, what have you done. Check the list of errors dude!"; 
    } 
    else 
    { 
     // Save it here... 

     // Return success 
     res.Status = Status.Ok; 
     res.Message = "Everything was hunky dory"; 
    }    

    return Json(res); 
} 

Y el ModelStateDictionary se pueden enumerar los errores como tan:

private List<string> GetModelStateErrorsAsString(ModelStateDictionary state) 
{ 
    List<string> errors = new List<string>(); 

    foreach (var key in ModelState.Keys) 
    { 
     var error = ModelState[key].Errors.FirstOrDefault(); 
     if (error != null) 
     { 
      errors.Add(error.ErrorMessage); 
     } 
    } 

    return errors; 
} 

Luego, en mi veo que puedo tener el siguiente JSON POST:

<script type="text/javascript"> 
$("form").submit(function (evt) { 
    // validate 
    $('form').valid(); 

    // extract values to submit   
    var form = $(this), 
     username = form.find("[name=Username]").val(), 
     password = form.find("[name=Password]").val(), 
     json = JSON.stringify({ 
      Username: username, 
      Password: password 
     }); 

    $.ajax({ 
     url: form.attr("action"), 
     type: 'POST', 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json', 
     data: json, 
     success: function (result) { 
      alert(result.Message); 
     } 
    }); 

    // stop form submitting 
    evt.preventDefault(); 
}); 
</script> 

Estoy usando jQuery.tmpl para mostrar los errores. Sin embargo, he excluido eso de este ejemplo.

+2

aplausos por la respuesta. No puedo probar esto en este momento ya que estoy de vacaciones. Espero que no te importe si lo dejo abierto hasta que vuelva. –

+0

@Junto ¿Por qué no haber usado un booleano en lugar de una enumeración? – Rushino

+1

@Rushino Puede extender la enumeración para incluir advertencias, por ejemplo, o información. Boolean te limita. – Junto

1

Gracias por esta solución. Mejoré un poco al pasar un diccionario para que pueda usar el javascript discreto para poner la validación en los campos individuales en lugar de un resumen al hacer referencia a la clave del diccionario.

private Dictionary<string, string> GetModelStateErrorsAsString(ModelStateDictionary state) 
    { 
     Dictionary<string, string> errors = new Dictionary<string, string>(); 
     foreach (var key in ModelState.Keys) 
     { 
      var error = ModelState[key].Errors.FirstOrDefault(); 
      if (error != null) 
      { 
       errors.Add(key, error.ErrorMessage); 
      } 
     } 
     return errors; 
    } 
+4

De hecho, me pregunto cómo está vinculando los errores de json a su formulario en el lado del cliente. ¿Podría explicarlo por favor? – mb666

0

@Junto y @ Jamey777, ambos pasan el ModelState a su función de error, pero a continuación, utiliza la variable global en lugar del parámetro.

y ¿por qué no sólo tiene que utilizar un poco de LINQ como

private Dictionary<string, string> GetModelStateErrorsAsString() 
    { 
     return ModelState.Where(x=> x.Value.Errors.Any()) 
      .ToDictionary(x => x.Key, x => x.Value.Errors.First().ErrorMessage); 
    } 
Cuestiones relacionadas