Pregunta

Hay un montón de post muy bueno y las explicaciones de cómo implementar la validación con ASP.NET MVC, y yo prefiero uno de los siguientes:

Sin embargo, me gusta mucho llamar ActionMethods vía método de jQuery $ .ajax. Una de las razones por las que quiero usar $ .ajax es porque habrá una gran cantidad de puntos de vista parciales cargados en la página de forma dinámica (incluso la forma de creación de entidades) a través de $ .ajax llamadas y no puedo simplemente volver la vista - voy a perder todo el contenido cargado dinámicamente.

Para darle una mejor visión sobre el problema, voy a publicar un código simple de explicar cómo me gustaría llamar a acciones de controladores y manejar las respuestas en el cliente, el código de jQuery.

Los controladores ActionMethod:

    public ActionResult CreateCustomer(string name, string accountNumber)
    {
        try
        {
            CustomerService.InsertCustomer(name, accountNumber);

            return Json(new ActionInfo()
            {
                Success = true,
                Message = "Customer Is Successfully Created"
            });

        }
        catch (Exception ex)
        {
            return Json(new ActionInfo()
            {
                Success = false,
                Message = ex.Message
            });
        }
    }

Llamadas y gastos de envío en el código de cliente:

$.ajax({
type: "POST",
url: $form.attr('action'),// /MyController/CreateCustomer
data: $form.serialize(),
error: HandleUnespectedError,
dataType: "json",
success: function(response) {

    if (response.Success)
        alert("Success: " + response.Message);
    else
        alert("Error: " + response.Message);
}});

¿Hay una buena manera de hacer que algunos de estos marcos de validación para trabajar de la manera que necesito? Sé que puedo añadir errores de validación en ActionInfo, y luego manejarlo de cliente, sino que se ya sea un edificio de mi una validación, creo.

¿Fue útil?

Solución

He tenido un gran éxito haciendo la validación a través de AJAX utilizando atributos anotaciones de datos. Con el fin de comprobar la validez de los datos, se tendrá que usar la propiedad ModelState del controlador, que tiene una propiedad de su propia llamada IsValid. Yo recomiendo echar un vistazo a la validación de datos de anotaciones atributos tutorial desde el sitio oficial ASP.NET MVC.

En primer lugar, tendrá que modificar su acción de controlador para aceptar el modelo de objetos como parámetro, en lugar de un nombre y número de cuenta separada. Esto hará que realiza la validación, que voy a demostrar más adelante, mucho más simple. De su ejemplo, mi mejor conjetura es que el objeto del modelo es, o sería, llama al cliente. Es posible que tenga el código siguiente para definir el objeto de modelo y su controlador de la acción ...

// model object
public class Customer
{
  public Int32 Id {get; set;}
  public String Name {get; set;}
  public String AccountNumber {get; set;}
}

// controller
public class CustomerController : Controller
{
  public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
  {
     // controller action code
  }
}


Asegúrese de que sus campos de formulario se nombran para que coincida con los nombres de las propiedades del objeto al cliente de modo ASP.NET MVC automagicamente puede obligar a ellos. El atributo "Bind", en este caso, está diciendo ASP.NET MVC hacer caso omiso de la propiedad "ID" de la clase Cliente al enlazar los campos del formulario para modelar propiedades. Dado que este es un nuevo cliente, no tenemos una identificación sin embargo, por lo que podemos dejar con seguridad la identificación que cualquiera que sea el valor por defecto es y dejar la capa de datos para averiguar la mejor manera de generar la misma.

Una vez que el controlador ha construido el objeto modelo para el método de acción, su validez se puede comprobar fácilmente a través de la propiedad ModelState.IsValid. Como era de esperar, devolverá verdadero si los del modelo son válidos, o falso si 1 o más propiedades no son válidos.

A partir de la pregunta original, parece que el método CustomerService.InsertCustomer es lanzar excepciones cuando falla la validación. Esto es completamente innecesario. InsertCustomer sólo se necesita para realizar cualquier operación de datos son necesarios para insertar el nuevo registro. A menos que desee excepciones específicas de implementación abstracta, como SqlException, InsertCustomer en realidad no debería tener que coger o lanzar excepciones, pero puede más probable es dejar que cualquier burbuja de excepciones hasta el controlador (o quien sea la persona que llama puede ser).

El resultado final de todo esto, podría ser una acción de controlador que se parece a lo siguiente:

public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
{
  // model is invalid
  if (!ModelState.IsValid)
  {
    return Json(new ActionInfo()
    {
      Success = false,
      Message = "Validation failed" // you will probably want a more robust message :-)
    });
  }

  // service method accepts a Customer object rather than arbitrary strings  
  CustomerService.InsertCustomer(customer);

  return Json(new ActionInfo()
  {
    Success = true,
    Message = "Customer created successfully."
  });

}


Si desea reportar errores inesperados, como excepciones relacionadas con bases de datos, a continuación, que sin duda puede añadir un bloque try / catch alrededor de la llamada a InsertCustomer, y devolver el resultado necesario para mostrar el mensaje de error de vuelta al cliente.

Otros consejos

Esto es más de un año después de haber pedido a su pregunta, pero me ha cubierto validación del lado del servidor con llamadas Ajax en mi entrada de blog nofollow que pueda ser de mucho interés para usted. Veo que devuelva resultados fallidos como llamadas HTTP exitosas. He manejado esto de manera diferente (supongo que es más correcto desde $.ajax tiene la capacidad de funcionalidad success y la respuesta error). Y el ejemplo particular es un ejemplo perfecto que podría implementarse con la funcionalidad explico en mi blog.

Básicamente en lugar de volver siempre una respuesta satisfactoria (pero con propiedades establecen para decirle al cliente que falló el procesamiento del lado del servidor) que en lugar de un tiro exeception en el servidor y manejarlo en consecuencia en el cliente. Estoy usando una clase ModelStateException personalizada junto con un filtro de acción HandleModelStateException.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top