2010-04-27 3 views
7

Я пытаюсь написать свой собственный атрибут пользовательской проверки, но у меня возникают некоторые проблемы.ASP MVC: Пользовательский атрибут проверки

Атрибут, который я пытаюсь написать, заключается в том, что когда пользователь входит в систему, пароль будет сравниваться с паролем подтверждения.

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; 
    } 
} 

Теперь моя проблема, когда я пытаюсь установить атрибут, как это в файле модели:

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


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

я получаю следующее сообщение об ошибке:

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

Кажется, что VS не принимает confirmpassword в части PasswordToCompareWith=ConfirmPassword.

Что я делаю неправильно?

ответ

4

Извините, что разочаровал вас, но обработка такого простого случая, как ваша, с использованием аннотаций данных может быть болью. Вы можете посмотреть this post.

+0

Это решит мою проблему! Спасибо за ссылку! :) – 2010-04-27 11:59:46

0

Вы не можете передать ссылочный тип в атрибут, если не используете какой-то довольно слабый код отражения.

В этой ситуации я бы подумал, что создание настраиваемого связующего будет лучшей идеей, а затем проверки пароля и ComparePassword в этот момент.

+0

Я думаю, что модельное связующее, безусловно, более хромает, чем использование DataAnnotations с отражением. Я считаю, что модельное связующее не должно определять правила проверки. – LukLed

+0

Я новичок, не могли бы вы объяснить, как отражения работают? – 2010-04-27 11:56:18

+0

Ха, это огромная дискуссионная тема.Я не мог правильно объяснить, что это короткое пространство, но я могу указать вам на хороший ресурс: http://msdn.microsoft.com/en-us/library/f7ykdhsy(VS.71).aspx – Tejs

1

FoolProof http://foolproof.codeplex.com/ представляется лучшим решением.

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

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

Это лучше, чем предполагалось PropertiesMustMatchAttribute, поскольку это добавляет ошибку проверки для «RetypePassword» вместо глобального уровня модели, как это делает PropertiesMustMatchAttribute.

18

По этой ссылке http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1 есть атрибут теперь специальная проверка в 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 говорит, что этот API устарел. http://msdn.microsoft.com/en-us/library/system.web.mvc.compareattribute(v=vs.118).aspx. По-видимому, они перемещали его в пространство имен System.ComponentModel.DataAnnotations. – Stack0verflow

2

Я не знаю, почему это сделано, чтобы быть такое большое дело, просто сделать Тхи 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; 
    } 
} 

Теперь все, что вам нужно сделать, это добавить [ComparePassword] к вашему свойству пароля, ничего не передать ... простой и довольно чистый

+0

Супер, но учитывая новый CompareAttribute @orcy, привлеченный к нашему вниманию, нет необходимости развертывать наши собственные. – Stack0verflow

+0

Это удовлетворительный демонстрационный код, но очевидная проблема заключается в повторном использовании; Он жестко закодирован для конкретной реализации ('YourRegistrationModel') с определенным свойством (' ConfirmPassword'). Если вы хотите использовать этот подход с более чем одной моделью, вам понадобятся несколько экземпляров или базовый тип/интерфейс PasswordModel. – JoeBrockhaus

0

вам нужен статический метод в вашем случае: Пример:

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

только в качестве примера:

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) 
     }; 
    } 
} 
    } 

источник: https://code.google.com/p/gdnetprojects/source/browse/trunk/Experiments/Common/GDNET.Web.Mvc/Validation/ValidatePasswordLengthAttribute.cs?r=69

Смежные вопросы