validator side net mvc framework dataannotations data custom asp annotation asp.net-mvc validation asp.net-mvc-2 data-annotations

side - ASP.NET MVC: ¿Es suficiente la validación de anotación de datos?



dataannotations mvc validation (5)

Estoy utilizando la validación de anotación de datos extensivamente en ASP.NET MVC 2. Esta nueva característica ha supuesto un gran ahorro de tiempo, ya que ahora puedo definir la validación del lado del cliente y la del lado del servidor en un solo lugar. Sin embargo, mientras hacía algunas pruebas detalladas, me di cuenta de que es bastante fácil para alguien eludir la validación del lado del servidor si dependiera solo de la validación de la Anotación de datos. Por ejemplo, si definí un campo obligatorio anotando la propiedad con el atributo [Obligatorio] y coloqué un cuadro de texto para ese campo obligatorio en un formulario, un usuario simplemente podría eliminar el cuadro de texto del DOM (que puede hacerse fácilmente a través de Firebug) y ahora la validación de anotación de datos no se activará en esa propiedad durante el enlace modelo dentro de un controlador. Para asegurar que se active la validación "requerida", puedo repetir la validación después de que ocurre la vinculación del modelo, pero entonces estaría repitiendo mi lógica de validación.

¿Cuál es la recomendación de todos sobre la validación? ¿La validación de anotación de datos es suficiente? ¿O es necesario repetir la validación para garantizar que las validaciones se activen en todas las situaciones?

Comentario de seguimiento: en base a las respuestas a continuación, parece que no puedo basarme solo en la validación de Model Binder y Annotation de datos. Dado que estamos concluyendo que se requiere una validación adicional del lado del servidor, ¿hay alguna manera fácil para que mi capa de Servicio active la validación en función de lo que se ha definido en las Anotaciones de datos? Parece que esto nos dará lo mejor de ambas palabras ... no necesitaremos repetir el código de validación, pero aún así nos aseguraremos de que la validación se ejecute incluso si la Carpeta del modelo no la desencadena.

Voy a publicar este comentario de seguimiento como una pregunta separada, ya que plantea una pregunta diferente a la original.


Creo que para estar atento a la seguridad, debe elegir que la validación del servidor sea la prioridad y asegurarse de que este sea siempre su respaldo. La validación de su servidor debería funcionar sin la validación del cliente. La validación del cliente es más para UX y eso es primordial para su diseño, es secundario a la seguridad. Con esto en mente, se encontrará repitiendo su validación. Un objetivo a menudo es tratar de diseñar su aplicación para que la validación del servidor y del cliente pueda integrarse tanto como sea posible para reducir el trabajo requerido para validar en el servidor y el cliente. Pero ten la seguridad de que debes hacer ambas cosas.

Si eludir la validación del cliente (por medio de la manipulación DOM) es evitar la validación del servidor (que parece que está indicando), entonces la validación de su servidor para esta instancia no puede emplearse adecuadamente. Debería invocar la validación de su servidor nuevamente en su acción de controlador o en una capa de servicio. El escenario que describes no debería estar derrotando la validación de tu servidor.

Con el escenario que describes, el método de atributos de anotación de datos debería ser suficiente. Parece que solo necesita hacer algunos cambios de código para asegurarse de que se invoque la validación de su servidor también al enviar el formulario.


Emparejé xVal con DataAnnotations y escribí mi propio filtro de acción que verifica cualquier parámetro de tipo de entidad con fines de validación. Por lo tanto, si falta algún campo en la devolución de datos, este validador rellenará el diccionario de ModelState y, por lo tanto, tendrá el modelo no válido.

Prerrequisitos:

  • los objetos de mi entidad / modelo implementan la interfaz IObjectValidator que declara el método Validate() .
  • mi clase de atributo se llama ValidateBusinessObjectAttribute
  • Biblioteca de validación xVal

Código de filtro de acción:

public void OnActionExecuting(ActionExecutingContext filterContext) { IEnumerable<KeyValuePair<string, object>> parameters = filterContext.ActionParameters.Where<KeyValuePair<string, object>>(p => p.Value.GetType().Equals(this.ObjectType ?? p.Value.GetType()) && p.Value is IObjectValidator); foreach (KeyValuePair<string, object> param in parameters) { object value; if ((value = param.Value) != null) { IEnumerable<ErrorInfo> errors = ((IObjectValidator)value).Validate(); if (errors.Any()) { new RulesException(errors).AddModelStateErrors(filterContext.Controller.ViewData.ModelState, param.Key); } } } }

Mi acción de controlador se define así:

[ValidateBusinessObject] public ActionResult Register(User user, Company company, RegistrationData registrationData) { if (!this.ModelState.IsValid) { return View(); } ... }


Escribí mi propio ValidationService para MVC 1.0 copiando patrones de ambos DataAnnotationsRuleProvider de xVal y DataAnnotationsModelBinder de Microsoft (y los comentarios de Martijn). La interfaz del servicio está a continuación:

public interface IValidationService { void Validate(object instance); IEnumerable<ErrorInfo> GetErrors(object instance); } public abstract class BaseValidationService : IValidationService { public void Validate(object instance) { var errors = GetErrors(instance); if (errors.Any()) throw new RulesException(errors); } public abstract IEnumerable<ErrorInfo> GetErrors(object instance); }

El servicio es un corredor de validación que recorre el árbol de propiedades de la instancia de objeto que recibe y realmente ejecuta los atributos de validación que encuentra en cada propiedad, creando una lista de objetos ErrorInfo cuando los atributos no son válidos. (Publicaba toda la fuente, pero fue escrita para un cliente y todavía no sé si estoy autorizado para hacerlo).

Luego puede tener sus controladores, los servicios de lógica de negocios invocan la validación explícitamente cuando esté listo, en lugar de confiar exclusivamente en el archivador modelo para la validación.

Hay un par de otras trampas que debes tener en cuenta:

  • El DataTypeAttribute predeterminado en las anotaciones de datos en realidad no realiza ninguna validación de tipo de datos, por lo que tendrá que escribir un nuevo atributo que realmente use expresiones regulares xVal (u otra cosa) para realizar la validación del tipo de datos del lado del servidor.
  • xVal no recorre las propiedades para crear una validación del lado del cliente, por lo que es posible que desee realizar algunos cambios allí para obtener una validación del lado del cliente más sólida.

Si estoy autorizado y tengo tiempo, intentaré hacer que haya más fuentes disponibles ...


La Anotación de Datos ciertamente no es suficiente. Lo uso extensivamente también para validar previamente mis llamadas al modelo de dominio para obtener mejores informes de errores y fallar tan pronto como sea posible.

Sin embargo, puede ajustar el Modelo de Anotación de Datos usted mismo para asegurarse de que las propiedades con [Obligatorio] DEBEN publicarse. (Seguiremos con el código más tarde hoy).

ACTUALIZAR Obtenga la fuente de DataAnnotations Model Binder y encuentre esta línea en DataAnnotationsModelBinder.cs

// Only bind properties that are part of the request if (bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey)) {

Cambiarlo a

// Only bind properties that are part of the request bool contextHasKey = bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey); bool isRequired = GetValidationAttributes(propertyDescriptor).OfType<RequiredAttribute>().Count() > 0; if (contextHasKey || (!contextHasKey && isRequired)) {


Ver validación de entrada del lado del servidor de codeProject usando anotaciones de datos

La validación de entrada se puede hacer automáticamente en el lado del cliente en ASP.NET MVC o validar explícitamente el modelo con las reglas. Este consejo describirá cómo se puede hacer manualmente en el lado del servidor de las aplicaciones ASP.NET o dentro del código de repositorio de las aplicaciones WPF.

// Use the ValidationContext to validate the Product model against the product data annotations // before saving it to the database var validationContext = new ValidationContext(productViewModel, serviceProvider: null, items:null); var validationResults = new List<ValidationResult>(); var isValid = Validator.TryValidateObject(productViewModel, validationContext,validationResults, true);