Sin embargo existen ocasiones en que estas validaciones no podemos definirlas de manera estática en la definición del modelo porque dependen de otras variables. Por ejemplo, ¿cómo definimos el rango de valores aceptados por un campo importe si el importe máximo depende del usuario que esté realizando la operación?
Por suerte la extensibilidad del framework de ASP.NET MVC nos permite crear nuestro propio proveedor de validaciones en el que podemos tener en cuenta circunstancias como ésta.
Para mostrar cómo podemos crear nuestro propio proveedor de validaciones voy a implementar un formulario de solicitudes de pedido en el que el importe máximo del artículo solicitado dependerá del usuario que lo solicita. Además, dependiendo del usuario que lo solicite, será obligatorio o no que especifique el motivo de la solicitud.
Este artículo voy a dedicarlo a crear el proyecto de ejemplo sobre el que implementar el proveedor de validaciones por lo que quien no esté interesado en seguir el ejemplo paso a paso puede pasar directamente al siguiente artículo (ASP.NET MVC. ModelValidatorProvider personalizado (y II) - Implementando el Proveedor) en el que creo el proveedor.
Creando el proyecto ejemplo
Así que voy a crear un nuevo proyecto de aplicación web CustomModelValidatorProvider y elegiré la plantilla de sitio vacío añadiendo las referencias a MVC.
Como las validaciones a utilizar van a depender del usuario necesitaremos crear una autenticación básica. En el Web.config voy a habilitar la autenticación basada en formularios estableciendo una url para la página de login y estableciendo dos usuarios diferentes (Jefe y Empleado), para lo que crearé el elemento authentication dentro de system.web.
<authentication mode="Forms"> <forms loginUrl="~/Login"> <credentials passwordFormat="Clear"> <user name="Jefe" password="contra"/> <user name="Empleado" password="contra"/> </credentials> </forms> </authentication>
Por supuesto que jamás se me ocurriría implementar la autenticación de un sitio web en producción de esta forma y, por favor, que nadie siga este ejemplo para hacerlo. Pero para nuestro ejemplo nos servirá: tenemos dos usuarios "Jefe" y "Empleado" (ambos con contraseña "contra") que nos permitirá diferenciar el comportamiento de la aplicación en función del usuario autenticado.
Necesitaremos también una página de login que nos permita validar el usuario y, si la validación es correcta, redirigirle al formulario de solicitud que tendremos en la página principal del sitio web.
Para ello voy a crear un modelo en un archivo Usuario.cs/Usuario.vb de la carpeta Model:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CustomModelValidatorProvider.Models { public class Usuario { [Required] [Display(Name = "Usuario")] public string NombreUsuario { get; set; } [Required] [UIHint("Password")] [Display(Name = "Contraseña")] public string Contrasena { get; set; } } }
Imports System.ComponentModel.DataAnnotations Public Class Usuario <Required> <Display(Name:="Usuario")> Property NombreUsuario As String <Required> <UIHint("Password")> <Display(Name:="Contraseña")> Property Contrasena As String End Class
Un controlador LoginController:
using CustomModelValidatorProvider.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace CustomModelValidatorProvider.Controllers { public class LoginController : Controller { public ViewResult Index() { return View(); } [HttpPost] public ActionResult Index(Usuario usuario, string returnUrl) { if (ModelState.IsValid) { if (FormsAuthentication.Authenticate(usuario.NombreUsuario, usuario.Contrasena)) { FormsAuthentication.SetAuthCookie(usuario.NombreUsuario, false); return Redirect(returnUrl ?? Url.Action("Index", "Home")); } else { ModelState.AddModelError("", "Usuario o contraseña incorrectos"); return View(); } } else return View(); } } }
Imports System.Web.Mvc Namespace Controllers Public Class LoginController Inherits Controller Function Index() As ViewResult Return View() End Function <HttpPost> Function Index(usuario As Usuario, returnUrl As String) As ActionResult If ModelState.IsValid Then If FormsAuthentication.Authenticate(usuario.NombreUsuario, usuario.Contrasena) Then FormsAuthentication.SetAuthCookie(usuario.NombreUsuario, False) If String.IsNullOrEmpty(returnUrl) Then Return Redirect(Url.Action("Index", "Home")) Else Return Redirect(returnUrl) End If Else ModelState.AddModelError("", "Usuario o contraseña incorrectos") Return View() End If Else Return View() End If End Function End Class End Namespace
Y una vista para la acción Index del controlador:
@model CustomModelValidatorProvider.Models.Usuario @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @using (Html.BeginForm()) { @Html.ValidationSummary() @Html.EditorForModel() <br /> <input type="submit" value="Validar" /> } </div> </body> </html>
@ModelType CustomModelValidatorProvider.Usuario @Code Layout = Nothing End Code <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @Using (Html.BeginForm()) @Html.ValidationSummary() @Html.EditorForModel() @:<br /> @:<input type="submit" value="Validar" /> End Using </div> </body> </html>
A continuación voy a crear el formulario para realizar la solicitud de pedido. En primer lugar crearé un modelo muy simple compuesto por los campos código y descripción del artículo solicitado, el precio y el motivo por el que se realiza la solicitud. Así que crearé el archivo SolicitudPedido.cs/SolicitudPedido.vb en la carpeta Models.
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CustomModelValidatorProvider.Models { public class SolicitudPedido { [Display(Name = "Código de Artículo")] [Required] public string CodigoArticulo { get; set; } [Display(Name = "Descripción")] [Required] public string DescripcionArticulo { get; set; } [Required] public double Precio { get; set; } [Display(Name = "Motivo de la Solicitud")] public string Motivo { get; set; } } }
Imports System.ComponentModel.DataAnnotations Public Class SolicitudPedido <Display(Name:="Código de Artículo")> <Required> Property CodigoArticulo As String <Display(Name:="Descripción")> <Required> Property DescripcionArticulo As String <Required> Property Precio As Double <Display(Name:="Motivo de la Solicitud")> Property Motivo As String End Class
Un controlador HomeController con dos acciones Index una para mostrar el formulario cuando la petición se realiza con el método HttpGet y otra para el método HttpPost para recuperar los datos de la solicitud y realizar la validación del modelo. El controlador lo he decorado con el atributo Authorize para que la aplicación se redirija al formulario de login si no se ha autenticado el usuario.
using CustomModelValidatorProvider.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace CustomModelValidatorProvider.Controllers { [Authorize] public class HomeController : Controller { public ViewResult Index() { return View(); } [HttpPost] public ViewResult Index(SolicitudPedido solicitud) { return View(solicitud); } } }
Imports System.Web.Mvc Namespace Controllers <Authorize> Public Class HomeController Inherits Controller Function Index() As ViewResult Return View() End Function <HttpPost> Function Index(solicitud As SolicitudPedido) As ViewResult Return View(solicitud) End Function End Class End Namespace
Y finalmente la vista con el formulario para rellenar la solicitud que utiliza como modelo la clase SolicitudPedido.
@model CustomModelValidatorProvider.Models.SolicitudPedido @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @using (Html.BeginForm()) { @Html.EditorForModel() <input type="submit" value="Validar" /> } </div> </body> </html>
@ModelType CustomModelValidatorProvider.SolicitudPedido @Code Layout = Nothing End Code <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @Using Html.BeginForm() @Html.EditorForModel() @:<input type="submit" value="Validar" /> End Using </div> </body> </html>
Si arrancamos la aplicación nos redirigirá automáticamente al formulario de login, el cual nos permitirá validarnos con los usuarios "Jefe" o "Empleado" (ambos con la contraseña "contra"). Una vez validados la aplicación nos muestra el formulario de solicitud de pedido en el que podemos comprobar, pulsando el botón "Validar", que se aplican las validaciones que hemos definido a través de los atributos del modelo.
Ya tenemos preparada la aplicación, pendiente de añadir las validaciones en función del usuario conectado.
En el siguiente artículo veremos cómo implementarlas creando nuestro propio proveedor de validadores.
Artículo siguiente:
ASP.NET MVC. ModelValidatorProvider personalizado (y II) - Implementando el Proveedor
El código
Puedes descargar el código de ejemplo de:
No hay comentarios:
Publicar un comentario