ASP.NET MVC: DataAnnotation ile Özel Doğrulama


110

String türünde 4 özelliğe sahip bir Modelim var. StringLength ek açıklamasını kullanarak tek bir özelliğin uzunluğunu doğrulayabileceğinizi biliyorum. Bununla birlikte, 4 özelliğin birleşik uzunluğunu doğrulamak istiyorum.

Bunu veri açıklama ile yapmanın MVC yolu nedir?

Bunu soruyorum çünkü MVC'de yeniyim ve kendi çözümümü oluşturmadan önce bunu doğru şekilde yapmak istiyorum.


2
Fluent Validation'a baktınız mı? Karmaşık senaryoları Veri Ek Açıklamalarından çok daha iyi yönetir
levelnis

Şiddetle tavsiye edilen çözümlere bir göz atın .... dotnetcurry.com/ShowArticle.aspx?ID=776
Niks

Cevapladığınız için teşekkürler. Akıcı Doğrulamayı kontrol edeceğim, hiç duymadım. Ve Niks, Darin temelde gönderdiğiniz bağlantıdaki makalenin açıkladığını yazdı. Yani, teşekkür ederim ... Harika şeyler!
Danny van der Kraan

Yanıtlar:


177

Özel bir doğrulama özelliği yazabilirsiniz:

public class CombinedMinLengthAttribute: ValidationAttribute
{
    public CombinedMinLengthAttribute(int minLength, params string[] propertyNames)
    {
        this.PropertyNames = propertyNames;
        this.MinLength = minLength;
    }

    public string[] PropertyNames { get; private set; }
    public int MinLength { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
        var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType<string>();
        var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length;
        if (totalLength < this.MinLength)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }
}

ve sonra bir görünüm modeliniz olabilir ve özelliklerinden birini bununla dekore edebilirsiniz:

public class MyViewModel
{
    [CombinedMinLength(20, "Bar", "Baz", ErrorMessage = "The combined minimum length of the Foo, Bar and Baz properties should be longer than 20")]
    public string Foo { get; set; }
    public string Bar { get; set; }
    public string Baz { get; set; }
}

4
Cevap verdiğin için teşekkürler, cevabını kabul ettim. Aslında biraz utanmış hissedin. Tüm çözümü yazdın! Hehe. Yalnızca maksimum uzunluğu kontrol etmek için IsValid işlevini değiştirmek gerekiyordu. Öyleyse, bu tür sorunlar için kabul edilen MVC çözümü bu mu?
Danny van der Kraan

7
@DannyvanderKraan, evet, kabul edilen yol bu. Elbette bu o kadar kötü ki, onu asla kullanmıyorum ve doğrulama yapmak için FluentValidation.NET kullanıyorum.
Darin Dimitrov

11
Buraya: fluentvalidation.codeplex.com . Sadece bu nasıl görünüyor olabileceğini görünümü modeli için basit bir doğrulayıcı (tek bir kod satırı) yazmış olabilirdi: this.RuleFor(x => x.Foo).Must((x, foo) => x.Foo.Length + x.Bar.Length + x.Baz.Length < 20).WithMessage("The combined minimum length of the Foo, Bar and Baz properties should be longer than 20");. Şimdi cevabımdaki veri notlarıyla yazmanız gereken koda bakın ve hangisini tercih ettiğinizi söyleyin. Bildirimsel doğrulama modeli, zorunlu bir modele kıyasla çok zayıf.
Darin Dimitrov

1
Bu biraz gecikti, ancak özel veri açıklamalarına izin vermek için "açmanız" gereken farklı bir ayar olup olmadığını bilen var mı? Web.config dosyasında göze batmayan js için bir ad alanı eklemeyi biliyorum, ancak başka bir yerde?
Jose

1
Ben arıyordum bu sabahtan! Yaptım ve maalesef null IsValidolarak adlandırıldığında validationContext. Neyi yanlış yaptığım hakkında bir fikrin var mı? :-(
Grimm The Opiner

96

Kendini doğrulayan model

Modeliniz bir arayüz uygulamalıdır IValidatableObject. Doğrulama kodunuzu Validateyönteme koyun :

public class MyModel : IValidatableObject
{
    public string Title { get; set; }
    public string Description { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Title == null)
            yield return new ValidationResult("*", new [] { nameof(Title) });

        if (Description == null)
            yield return new ValidationResult("*", new [] { nameof(Description) });
    }
}

Lütfen dikkat: Bu bir sunucu tarafı doğrulamadır. İstemci tarafında çalışmıyor. Doğrulamanız yalnızca form gönderildikten sonra gerçekleştirilecektir.


Andrei'ye cevap verdiğiniz için teşekkürler. Çözümünüz de işe yarayacak olsa da, Darin'i seçiyorum çünkü daha yeniden kullanılabilir.
Danny van der Kraan

6
getiri yeni ValidationResult ("Başlık zorunludur.", "Başlık"); özellik adını ekler, gerekirse görüntüleme için doğrulama hatalarının gruplanmasında yararlıdır.
Mike Kingscott

5
Bu doğrulama yönteminin yalnızca tüm doğrulama özniteliklerinin doğrulamayı geçtikten sonra çağrıldığını unutmayın.
Pedro

3
Doğrulamam çok spesifik olduğu için bu benim için iyi çalıştı. Doğrulama yeniden kullanılmayacağı için özel bir öznitelik eklemek benim için fazla olurdu.
Steve S

Aradığım şey bu. Teşekkür ederim!
Amol Jadhav

27

ExpressiveAnnotations size böyle bir olasılık verir:

[Required]
[AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")]
public string FieldA { get; set; }

Bu harika! dualarım cevaplandı :)
Korayem

Bu cevabı yeni buldum ve çok zaman kazandırdı. ExpressiveAnnotations harika!
Brad

10

Darin'in cevabını iyileştirmek için biraz daha kısa olabilir:

public class UniqueFileName : ValidationAttribute
{
    private readonly NewsService _newsService = new NewsService();

    public override bool IsValid(object value)
    {
        if (value == null) { return false; }

        var file = (HttpPostedFile) value;

        return _newsService.IsFileNameUnique(file.FileName);
    }
}

Model:

[UniqueFileName(ErrorMessage = "This file name is not unique.")]

Bir hata mesajı gerektiğini unutmayın, aksi takdirde hata boş olacaktır.


8

Arka fon:

Aldığımız verilerin geçerli ve doğru olduğundan emin olmak için model doğrulamaları gereklidir, böylece bu verilerle daha fazla işlem yapabiliriz. Bir eylem yönteminde bir modeli doğrulayabiliriz. Yerleşik doğrulama öznitelikleri, Karşılaştır, Aralık, RegularExpression, Gerekli, StringLength'dur. Bununla birlikte, yerleşik olanlar dışında doğrulama özniteliklerine ihtiyaç duyduğumuz senaryolarımız olabilir.

Özel Doğrulama Özellikleri

public class EmployeeModel 
{
    [Required]
    [UniqueEmailAddress]
    public string EmailAddress {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public int OrganizationId {get;set;}
}

Özel bir doğrulama özniteliği oluşturmak için bu sınıfı ValidationAttribute'tan türetmeniz gerekir.

public class UniqueEmailAddress : ValidationAttribute
{
    private IEmployeeRepository _employeeRepository;
    [Inject]
    public IEmployeeRepository EmployeeRepository
    {
        get { return _employeeRepository; }
        set
        {
            _employeeRepository = value;
        }
    }
    protected override ValidationResult IsValid(object value,
                        ValidationContext validationContext)
    {
        var model = (EmployeeModel)validationContext.ObjectInstance;
        if(model.Field1 == null){
            return new ValidationResult("Field1 is null");
        }
        if(model.Field2 == null){
            return new ValidationResult("Field2 is null");
        }
        if(model.Field3 == null){
            return new ValidationResult("Field3 is null");
        }
        return ValidationResult.Success;
    }
}

Bu yardımcı olur umarım. Şerefe!

Referanslar


1

Cevap vermek için biraz geç ama arayan kim için. Bunu, veri ek açıklamasına ek bir özellik kullanarak kolayca yapabilirsiniz:

public string foo { get; set; }
public string bar { get; set; }

[MinLength(20, ErrorMessage = "too short")]
public string foobar 
{ 
    get
    {
        return foo + bar;
    }
}

Hepsi bu kadar gerçekten. Doğrulama hatasını gerçekten belirli bir yerde görüntülemek istiyorsanız, bunu görünümünüze ekleyebilirsiniz:

@Html.ValidationMessage("foobar", "your combined text is too short")

Bunu görünümde yapmak yerelleştirme yapmak istiyorsanız kullanışlı olabilir.

Bu yardımcı olur umarım!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.