error con jquery asp.net-mvc ajax partial-views

jquery - Cómo manejar los errores de estado del modelo en la acción del controlador invocada ajax que devuelve un PartialView



ajax error function (2)

Tengo una acción de controlador POST que devuelve una vista parcial. Todo parece muy fácil. pero. Lo cargo usando $.ajax() , estableciendo el tipo como html . Pero cuando la validación de mi modelo falla, creo que debería arrojar un error con los errores de estado del modelo. Pero mi respuesta siempre devuelve el error 500 Server.

¿Cómo puedo informar los errores de estado del modelo sin devolver Json con el resultado que sea? Me gustaría devolver una vista parcial que pueda adjuntar directamente a algún elemento HTML.

Editar

También me gustaría evitar devolver la vista parcial de error. Esto se vería como un éxito en el cliente. Hacer que el cliente analice el resultado para ver si es un éxito real es propenso a errores. Los diseñadores pueden cambiar la salida de vista parcial y esto solo rompería la funcionalidad. Así que quiero lanzar una excepción, pero con el mensaje de error correcto devuelto al cliente ajax.


Prueba esto.

public ActionResult DoAjaxAction(Entity entity) { if(ModelState.IsValid) { return PartialView("Valid_View", entity); } else { return PartialView("Invalid_View", entity); } }


Solución

Tuve que escribir dos partes separadas que funcionan automágicamente exactamente como se esperaba .

Entonces debería devolver una vista parcial cuando el proceso de acción del controlador tiene éxito y debería arrojar un error con algunos detalles de falla cuando las cosas no están bien, así que las cosas del lado del cliente distinguirían el éxito y el fracaso en lugar de manejar siempre el éxito.

Hay dos partes principales que se utilizan para lograr esto:

  • Una clase de excepción personalizada que se lanza cuando algo sale mal para que podamos distinguir entre excepciones generales que pueden suceder en cualquier momento por cualquier razón y errores relacionados con nuestro procesamiento (el estado del modelo más notable es el no válido)
  • Filtro de acción de excepción que capta nuestra excepción personalizada y prepara el resultado según esa excepción; Como verá en el código, nuestra excepción personalizada guardará información sobre los errores de estado del modelo, por lo que este filtro podrá devolver código de estado HTTP personalizado así como cierta información textual.

En detalles, entonces ...

Enlace externo : toda esta información (explicación detallada y todo el código) también está disponible en mi blog. Las últimas actualizaciones de código siempre se publicarán allí .

Clase de excepción personalizada

Esta clase proporciona dos cosas

  1. hacer que sea simple distinguir los errores de estado del modelo de las excepciones regulares
  2. proporcionar algunas funcionalidades básicas que puedo usar más tarde

Esta clase se usa luego en mi filtro de error personalizado.

public class ModelStateException : Exception { public Dictionary<string, string> Errors { get; private set; } public ModelStateDictionary ModelState { get; private set; } public override string Message { get { if (this.Errors.Count > 0) { return this.Errors.First().Value; } return null; } } private ModelStateException() { this.Errors = new Dictionary<string, string>(); } public ModelStateException(ModelStateDictionary modelState) : this() { this.ModelState = modelState; if (!modelState.IsValid) { foreach (KeyValuePair<string, ModelState> state in modelState) { if (state.Value.Errors.Count > 0) { this.Errors.Add(state.Key, state.Value.Errors[0].ErrorMessage); } } } } }

Atributo de filtro de error

Este atributo ayuda a devolver errores al cliente en términos de códigos de error HTTP cuando hay errores de estado del modelo.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public class HandleModelStateExceptionAttribute : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } if (filterContext.Exception != null && typeof(ModelStateException).IsInstanceOfType(filterContext.Exception) && !filterContext.ExceptionHandled) { filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8; filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8; filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; filterContext.HttpContext.Response.StatusCode = 400; filterContext.HttpContext.Response.StatusDescription = (filterContext.Exception as ModelStateException).Message; } } }

Después de eso, simplemente decoré mi acción de controlador con mi atributo y voila. Obtuve errores en el cliente con el código 400 y la información correcta que configuré en mi filtro. Esta información luego se muestra al usuario (cuando está relacionada con los errores de estado del modelo, muestra la información que los campos de formulario deben modificar para que el formulario sea válido).

[HandleModelStateException] public ActionResult AddComment(MyModel data) { // check if state is valid if (!this.ModelState.IsValid) { throw new ModelStateException(this.ModelState); } // get data from store return PartialView("Comment", /* store data */ ); }

Esto hace que mi código sea reutilizable con cualquier error de estado del modelo y estos serán enviados al cliente como deberían.

Un solo problema (ahora se resuelve)

Pero todavía hay un problema relacionado con este código. Cuando mi filtro de acción de error establece StatusDescription y esa cadena contiene algunos caracteres especiales como Č, recibo basura en el cliente. A menos que use IE (estoy usando la versión 8). FF y CH muestran basura. Es por eso que establezco codificaciones pero no funciona. Si alguien tiene una solución para esta particularidad, estaría más que feliz de escucharla.
Si devuelvo un mensaje de error en el contenido, todo está bien. La codificación es correcta y puedo mostrar lo que quiera.