2010-04-27 20 views
7

Estoy intentando escribir mi propio atributo de Validación personalizada, pero tengo algunos problemas.ASP MVC: Atributo de validación personalizado

El atributo que intento escribir es que cuando un usuario inicia sesión, la contraseña se compara con la contraseña de confirmación.

namespace Data.Attributes 
{ 
public class ComparePassword : ValidationAttribute 
{ 
    public string PasswordToCompareWith { get; set; } 

    public override bool IsValid(object value) 
    { 
     if (PasswordToCompareWith == (string)value) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

Ahora mi problema es cuando estoy tratando de establecer el atributo de este tipo en el archivo de modelo:

[Required] 
    [ComparePassword(PasswordToCompareWith=ConfirmPassword)] 
    public string Password { get; set; } 


    [Required] 
    public string ConfirmPassword { get; set; } 
    } 

me sale el siguiente error:

Error 1 An object reference is required for the non-static field, method, or property 'Project.Data.Models.GebruikerRegistreerModel.ConfirmPassword.get'

Parece que VS no acepta el confirmpassword en la parte PasswordToCompareWith=ConfirmPassword.

¿Qué estoy haciendo mal?

Respuesta

4

Lamento decepcionarte pero manejar un caso tan simple como el tuyo usando anotaciones de datos podría ser una molestia. Puede echar un vistazo al this post.

+0

¡Esto resolverá mi problema! Gracias por el compañero de enlace! :) –

0

No puede pasar un tipo de referencia a un atributo a menos que haga un código de reflexión bastante cojo.

En esta situación, creo que crear una carpeta de modelo personalizado sería una mejor idea y luego verificar la Contraseña y ComparePassword en ese punto.

+0

Creo que la carpeta del modelo es definitivamente más coja que usar DataAnnotations con reflexión. Creo que la carpeta de modelo no debe definir reglas de validación. – LukLed

+0

Soy un poco nuevo, ¿podría explicar cómo funcionan las reflexiones? –

+0

Ja, ese es un gran tema de discusión.No pude explicar correctamente que este es un espacio corto, pero puedo indicarle un buen recurso: http://msdn.microsoft.com/en-us/library/f7ykdhsy(VS.71).aspx – Tejs

1

FoolProof http://foolproof.codeplex.com/ parece ser la mejor solución.

public class SignUpViewModel 
{ 
    [Required] 
    public string Password { get; set; } 

    [EqualTo("Password", ErrorMessage="Passwords do not match.")] 
    public string RetypePassword { get; set; } 
} 

Es mejor que sugirió PropertiesMustMatchAttribute ya que añade el error de validación para el "RetypePassword' en lugar del nivel modelo global como lo hace PropertiesMustMatchAttribute.

18

De acuerdo con este enlace http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1 hay una validación especial atributo ahora en MVC3:

public class RegisterModel 
{ 
    // skipped 

    [Required] 
    [ValidatePasswordLength] 
    [DataType(DataType.Password)] 
    [Display(Name = "Password")] 
    public string Password { get; set; }      

    [DataType(DataType.Password)] 
    [Display(Name = "Confirm password")] 
    [Compare("Password", ErrorMessage = "The password and confirmation do not match.")] 
    public string ConfirmPassword { get; set; } 
} 

CompareAttribute is a new, very useful validator that is not actually part of System.ComponentModel.DataAnnotations, but has been added to the System.Web.Mvc DLL by the team. Whilst not particularly well named (the only comparison it makes is to check for equality, so perhaps EqualTo would be more obvious), it is easy to see from the usage that this validator checks that the value of one property equals the value of another property. You can see from the code, that the attribute takes in a string property which is the name of the other property that you are comparing. The classic usage of this type of validator is what we are using it for here: password confirmation.

+0

MSDN dice que esta API ha quedado obsoleta. http://msdn.microsoft.com/en-us/library/system.web.mvc.compareattribute(v=vs.118).aspx. Aparentemente lo han movido bajo el espacio de nombres 'System.ComponentModel.DataAnnotaciones'. – Stack0verflow

2

no sé por qué esto está hecho para ser un gran problema, simplemente do Thi s:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)] 
public class ComparePassword: ValidationAttribute 
{ 
    public ComparePassword() 
     : base("Passwords must match.") { } 

    protected override ValidationResult IsValid (object value, ValidationContext validationContext) 
    { 
     if (value == null) return new ValidationResult("A password is required."); 

     // Make sure you change YourRegistrationModel to whatever the actual name is 
     if ((validationContext.ObjectType.Name != "YourRegistrationModel") 
      return new ValidationResult("This attribute is being used incorrectly."); 
     if (((YourRegistrationModel)validationContext.ObjectInstance).ConfirmPassword != value.ToString()) 
      return new ValidationResult("Passwords must match."); 

     return ValidationResult.Success; 
    } 
} 

Ahora todo lo que necesita hacer es añadir [ComparePassword] a su propiedad de contraseña, nada que pasan ... simple y bastante limpio

+0

Super, pero dado el nuevo CompareAttribute @orcy que llamamos nuestra atención, no es necesario implementar el nuestro. – Stack0verflow

+0

Este es un código de demostración satisfactorio, pero el problema obvio con esto es la reutilización; Está codificado para una implementación específica ('YourRegistrationModel') con una propiedad específica (' ConfirmPassword'). Si desea utilizar este enfoque con más de un modelo, necesitará varias instancias o una base tipo/interfaz tipo de contraseña, por ejemplo. – JoeBrockhaus

0

se necesita un método estático en su caso: Ejemplo:

 public static ValidationResult ValidateFrequency(double frequency, ValidationContext context) 
    { 
     if(context == null) 
     { 
      return (ValidationResult.Success); 
     } 
    } 
0

sólo como un ejemplo:

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Globalization; 
using System.Web.Mvc; 
using System.Web.Security; 

namespace GDNET.Web.Mvc.Validation 
{ 
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 
public sealed class ValidatePasswordLengthAttribute : ValidationAttribute, IClientValidatable 
{ 
    private const string defaultErrorMessage = "'{0}' must be at least {1} characters long."; 
    private readonly int minRequiredPasswordLength = Membership.Provider.MinRequiredPasswordLength; 

    public ValidatePasswordLengthAttribute() 
     : base(defaultErrorMessage) 
    { 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, minRequiredPasswordLength); 
    } 

    public override bool IsValid(object value) 
    { 
     string valueAsString = value as string; 
     return (valueAsString != null && valueAsString.Length >= minRequiredPasswordLength); 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     return new[] 
     { 
      new ModelClientValidationStringLengthRule(FormatErrorMessage(metadata.GetDisplayName()), minRequiredPasswordLength, int.MaxValue) 
     }; 
    } 
} 
    } 

fuente: https://code.google.com/p/gdnetprojects/source/browse/trunk/Experiments/Common/GDNET.Web.Mvc/Validation/ValidatePasswordLengthAttribute.cs?r=69

Cuestiones relacionadas