DataAnnotationsModelValidatorProvider.RegisterAdapter di ASP.Net Core MVC

Di ASP.Net MVC 5, validator anotasi data khusus dapat diimplementasikan dengan mewarisi DataAnnotationsModelValidator dan mendaftar menggunakan DataAnnotationsModelValidatorProvider.RegisterAdapter(...). Di ASP.Net Core MVC, bagaimana saya bisa mencapai ini?

Saya menemukan pertanyaan serupa di ASP.net core MVC 6 Data Pemisahan anotasi menjadi perhatian, tetapi adakah yang bisa menunjukkan kepada saya contoh kode sederhana?


person Community    schedule 23.08.2016    source sumber


Jawaban (2)


Menurut saya ASP.NET Core MVC tidak lagi mendukung DataAnnotationsModelValidatorProvider.RegisterAdapter. Solusi yang saya temukan adalah sebagai berikut:

Misalkan saya ingin mengubah Validator untuk RequiredAttribute menjadi adaptor validator saya sendiri (MyRequiredAttributeAdaptor), Mengubah pesan kesalahan default EmailAddressAttribute, dan mengubah Sumber Pesan Kesalahan Lokal untuk 'CompareAttribute' menjadi pesan saya sendiri.

1- Buat ValidationAttributeAdapterProvider khusus

using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.AspNetCore.Mvc.DataAnnotations.Internal;
using Microsoft.Extensions.Localization;
using System.ComponentModel.DataAnnotations;

public class CustomValidationAttributeAdapterProvider
    : ValidationAttributeAdapterProvider, IValidationAttributeAdapterProvider
{
    public CustomValidationAttributeAdapterProvider() { }

    IAttributeAdapter IValidationAttributeAdapterProvider.GetAttributeAdapter(
        ValidationAttribute attribute,
        IStringLocalizer stringLocalizer)
    {
        IAttributeAdapter adapter;
        if (attribute is RequiredAttribute)
        {
            adapter = new MyRequiredAttributeAdaptor((RequiredAttribute) attribute, stringLocalizer);
        }
        else if (attribute is EmailAddressAttribute)
        {
            attribute.ErrorMessage = "Invalid Email Address.";
            adapter = base.GetAttributeAdapter(attribute, stringLocalizer);
        }
        else if (attribute is CompareAttribute)
        {
            attribute.ErrorMessageResourceName = "InvalidCompare"; 
            attribute.ErrorMessageResourceType = typeof(Resources.ValidationMessages);
            var theNewattribute = attribute as CompareAttribute;
            adapter = new CompareAttributeAdapter(theNewattribute, stringLocalizer);
        }
        else
        {
            adapter = base.GetAttributeAdapter(attribute, stringLocalizer);
        }

        return adapter;
    }
}

2- Tambahkan CustomValidationAttributeAdapterProvider untuk memulai:

Tambahkan baris berikut ke public void ConfigureServices(IServiceCollection services) di Startup.cs:

services.AddSingleton <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider> ();

Berikut adalah adaptor MyRequiredAttributeAdaptor:

using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Localization;
using Microsoft.AspNetCore.Mvc.DataAnnotations.Internal;

public class MyRequiredAttributeAdaptor : AttributeAdapterBase<RequiredAttribute>
{
    public MyRequiredAttributeAdaptor(RequiredAttribute attribute, IStringLocalizer stringLocalizer)
        : base(attribute, stringLocalizer)
    {
    }

    public override void AddValidation(ClientModelValidationContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        MergeAttribute(context.Attributes, "data-val", "true");
        MergeAttribute(context.Attributes, "data-val-required", GetErrorMessage(context));
    }

    /// <inheritdoc />
    public override string GetErrorMessage(ModelValidationContextBase validationContext)
    {
        if (validationContext == null)
        {
            throw new ArgumentNullException(nameof(validationContext));
        }

        return GetErrorMessage(validationContext.ModelMetadata, validationContext.ModelMetadata.GetDisplayName());
    }
}

Referensi:

1- Lihat contoh Microsoft: Proyek entropi: Ini adalah contoh bagus untuk berbagai fitur .NET Core. Dalam pertanyaan ini: lihat implementasi MinLengthSixAttribute dalam sampel Mvc.LocalizationSample.Web:

https://github.com/aspnet/Entropy/tree/master/samples/Mvc.LocalizationSample.Web

2- Untuk melihat cara kerja adaptor atribut, lihat asp.Microsoft.AspNetCore.Mvc.DataAnnotations di github:

https://github.com/aspnet/Mvc/tree/master/src/Microsoft.AspNetCore.Mvc.DataAnnotations

person Amir    schedule 15.11.2016

Untuk menentukan validator khusus berdasarkan anotasi, Anda dapat menentukan kelas Anda sendiri yang berasal dari ValidationAttribute dan mengganti metode IsValid. Tidak perlu mendaftarkan kelas ini secara eksplisit.

Dalam contoh ini atribut validasi khusus digunakan untuk hanya menerima angka ganjil sebagai nilai valid.

public class MyModel
{
    [OddNumber]
    public int Number { get; set; }
}

public class OddNumberAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        try
        {
            var number = (int) value;
            if (number % 2 == 1)
                return ValidationResult.Success;
            else
                return new ValidationResult("Only odd numbers are valid.");
        }
        catch (Exception)
        {
            return new ValidationResult("Not a number.");
        }            
    }
}

Pendekatan kedua adalah kelas Model mengimplementasikan IValidatableObject. Hal ini sangat berguna, jika validasi memerlukan akses ke beberapa anggota kelas model. Berikut adalah validator bilangan ganjil versi kedua:

public class MyModel : IValidatableObject
{
    public int Number { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Number % 2 == 0)
            yield return new ValidationResult(
                 "Only odd numbers are valid.", 
                 new [] {"Number"});
    }
}

Anda dapat menemukan informasi selengkapnya tentang validasi khusus di https://docs.asp.net/en/latest/mvc/models/validation.html#custom-validation.

person Ralf Bönning    schedule 23.08.2016
comment
Terimakasih atas balasan anda. Tetapi saya ingin menggunakan validasi sisi server dan sisi klien, dan juga logika pemisahan perhatian, untuk tujuan ini, saya membuat - public class RequiredIfValidationAttribute : ValidationAttribute { // ... }, dan public class RequiredIfValidationAdaptor : AttributeAdapterBase<RequiredIfValidationAttribute> { // ...}, tetapi saya tidak tahu cara mendaftarkan adaptor itu di ASP. MVC Inti Bersih. Di MVC 5, saya menggunakan DataAnnotationsModelValidatorProvider.RegisterAdapter(...). Apakah Anda punya ide lagi? - person ; 24.08.2016