DataAnnotationsModelValidatorProvider.RegisterAdapter ใน ASP.Net Core MVC

ใน ASP.Net MVC 5 ตัวตรวจสอบคำอธิบายประกอบข้อมูลที่กำหนดเองสามารถนำมาใช้ได้โดยการสืบทอด DataAnnotationsModelValidator และการลงทะเบียนโดยใช้ DataAnnotationsModelValidatorProvider.RegisterAdapter(...) ใน ASP.Net Core MVC ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร

ฉันพบคำถามที่คล้ายกันที่ ASP.net core MVC 6 Data คำอธิบายประกอบแยกข้อกังวล แต่ใครสามารถแสดงโค้ดตัวอย่างง่ายๆ ให้ฉันได้บ้าง


person Community    schedule 23.08.2016    source แหล่งที่มา


คำตอบ (2)


สำหรับฉันดูเหมือนว่า ASP.NET Core MVC จะไม่รองรับ DataAnnotationsModelValidatorProvider.RegisterAdapter อีกต่อไป วิธีแก้ปัญหาที่ฉันค้นพบมีดังนี้:

สมมติว่าฉันต้องการเปลี่ยน Validator สำหรับ RequiredAttribute เป็นอะแดปเตอร์ตรวจสอบความถูกต้องของฉันเอง (MyRequiredAttributeAdaptor) เปลี่ยนข้อความแสดงข้อผิดพลาดเริ่มต้นที่ EmailAddressAttribute และเปลี่ยนแหล่งที่มาของข้อความแสดงข้อผิดพลาดที่แปลเป็นภาษาท้องถิ่นสำหรับ 'CompareAttribute' เป็นข้อความของฉันเอง

1- สร้าง ValidationAttributeAdapterProvider แบบกำหนดเอง

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- เพิ่ม CustomValidationAttributeAdapterProvider เพื่อเริ่มต้น:

เพิ่มบรรทัดต่อไปนี้ใน public void ConfigureServices(IServiceCollection services) ใน Startup.cs:

services.AddSingleton <IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider> ();

นี่คืออะแดปเตอร์ 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());
    }
}

ข้อมูลอ้างอิง:

1- ดูตัวอย่างของ Microsoft: โครงการเอนโทรปี: นี่คือตัวอย่างที่ยอดเยี่ยมสำหรับคุณสมบัติต่างๆ ของ .NET Core ในคำถามนี้: ดูการใช้งาน MinLengthSixAttribute ในตัวอย่าง Mvc.LocalizationSample.Web:

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

2- หากต้องการดูวิธีการทำงานของอะแดปเตอร์แอตทริบิวต์ โปรดดูที่ asp.Microsoft.AspNetCore.Mvc.DataAnnotations บน github:

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

person Amir    schedule 15.11.2016

หากต้องการกำหนดเครื่องมือตรวจสอบความถูกต้องที่กำหนดเองด้วยคำอธิบายประกอบ คุณสามารถกำหนดคลาสของคุณเองที่ได้มาจาก ValidationAttribute และแทนที่เมธอด IsValid ไม่จำเป็นต้องลงทะเบียนชั้นเรียนนี้อย่างชัดเจน

ในตัวอย่างนี้ คุณลักษณะการตรวจสอบความถูกต้องที่กำหนดเองใช้เพื่อยอมรับเฉพาะตัวเลขคี่เป็นค่าที่ถูกต้อง

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

แนวทางที่สองคือคลาส Model ใช้งาน IValidatableObject สิ่งนี้มีประโยชน์อย่างยิ่ง หากการตรวจสอบความถูกต้องจำเป็นต้องเข้าถึงสมาชิกหลายคนของคลาสโมเดล นี่คือเวอร์ชันที่สองของเครื่องมือตรวจสอบเลขคี่:

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

คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบแบบกำหนดเองได้ใน https://docs.asp.net/en/latest/mvc/models/validation.html#custom-validation

person Ralf Bönning    schedule 23.08.2016
comment
ขอบคุณสำหรับการตอบกลับของคุณ. แต่ฉันต้องการใช้การตรวจสอบทั้งฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ และยังแยกตรรกะข้อกังวลด้วย เพื่อจุดประสงค์นี้ ฉันจึงสร้าง - public class RequiredIfValidationAttribute : ValidationAttribute { // ... } และ public class RequiredIfValidationAdaptor : AttributeAdapterBase<RequiredIfValidationAttribute> { // ...}, แต่ฉันไม่รู้ว่าจะลงทะเบียนอะแดปเตอร์นั้นใน ASP ได้อย่างไร MVC หลักของเน็ต ใน MVC 5 ฉันใช้ DataAnnotationsModelValidatorProvider.RegisterAdapter(...) คุณมีความคิดเพิ่มเติมหรือไม่? - person ; 24.08.2016