سمة التحقق المخصصة والتحقق من صحة Blazor

· 4 دقيقة قراءة

#تخصيص كل شيء

كما رأيت على الأرجح في كل منشوراتي، أحاول حقًا الحفاظ على كل شيء نظيفًا قدر الإمكان، حيث أنني كتبت بالفعل منشورات تتعلق بالسمات المخصصة، ومعالجة الاستثناءات المخصصة، وحقن مجموعة الخدمات، وما إلى ذلك.

لقد أدركت مع مرور الوقت أن هذا النوع من طريقة البرمجة يمنحني وفريقي طريقة لتحسين العمل الإضافي، والعثور على المشكلات بشكل أسهل وفصل التعليمات البرمجية قدر الإمكان.

نعم، بعد هذه القصة الرائعة، لقد كنت أعمل على Blazor مؤخرًا كالمعتاد ووجدت أنه بعد سنوات وسنوات من التطوير، يمكنك إنشاء سمات تحقق مخصصة.

نعم إنه أمر مضحك، بعد كل هذه السنوات…

سمات التحقق المخصصة

في الواقع، جاءت الفكرة من العمل، فنحن نقوم دائمًا بالتحقق من الصحة في جميع الأماكن ولكن كان لدي بعض الحقول التي تتطلب نفس عملية التحقق من الصحة، لذلك اعتقدت أنه قد يكون هناك شيء ما هناك…. مثل سمات التحقق المخصصة!

لذلك قمت بتشغيل وثائق Microsoft لذلك واكتشفت أنه نعم، يمكنك إنشاء سمات تحقق مخصصة وتعيينها للخصائص، تمامًا مثل هذا:

public class StringLengthRangeAttribute : ValidationAttribute
{
    public int Minimum { get; set; }
    public int Maximum { get; set; }

    public StringLengthRangeAttribute()
    {
        this.Minimum = 0;
        this.Maximum = int.MaxValue;
    }

    public override bool IsValid(object value)
    {
        string strValue = value as string;
        if (!string.IsNullOrEmpty(strValue))
        {
            int len = strValue.Length;
            return len >= this.Minimum && len <= this.Maximum;
        }
        return true;
    }
}

واستخدامها في فئة بسيطة مثل هذا:

[Required]
[StringLengthRange(Minimum = 10, ErrorMessage = "Must be >10 characters.")]

[StringLengthRange(Maximum = 20)]

[Required]
[StringLengthRange(Minimum = 10, Maximum = 20)]

مدقق مخصص

لذا، لدي أداة التحقق هذه التي أحتاجها لبعض حالات العمل المحددة التي ستحتوي على 20 حرفًا أولًا تستبدل 9 أرقام وواصلة، وتنتهي بحرفين يمثلان عادةً رمز البلد، لذلك شيء من هذا القبيل: 123456789-123456789-ES

انتهى بي الأمر بشيء مثل هذا، إنه بسيط حقًا ولكنه يعمل:

using System;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

public class SpecialStringValidatorAttribute : ValidationAttribute
{
    private const int TotalLength = 22;
    private const string Pattern = @"^(\d{10})-(\d{10})-([A-Za-z]{2})$";

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        string strValue = value as string;

        if (!string.IsNullOrEmpty(strValue))
        {
            if (strValue.Length != TotalLength)
            {
                return new ValidationResult($"The string must be {TotalLength} characters long.");
            }

            if (!Regex.IsMatch(strValue, Pattern))
            {
                return new ValidationResult("The string must follow the pattern: 1234567890-1234567890-AB");
            }

            return ValidationResult.Success;
        }

        return new ValidationResult("The string cannot be null or empty.");
    }
}

الاختبارات

لقد كتبت بعض الاختبارات لهم أيضًا، فقط في حالة:

public class SpecialStringValidatorTests
{
    [Theory]
    [InlineData("1234567890-1234567890-AB", true)]
    [InlineData("1234567890-1234567890-XY", true)]
    [InlineData("1234567890-1234567890-A1", false)]
    [InlineData("1234567890-1234567890-A", false)]
    [InlineData("1234567890-123456789-AB", false)]
    [InlineData("1234567890-1234567890", false)]
    [InlineData("1234567890-1234567890-ABCDE", false)]
    public void SpecialStringValidatorTest(string input, bool expectedResult)
    {
        // Arrange
        var validator = new SpecialStringValidatorAttribute();

        // Act
        var result = validator.IsValid(input);

        // Assert
        Assert.Equal(expectedResult, result);
    }
}

وعندما ركضت حصلت على هذه النتائج:

Microsoft (R) Test Execution Command Line Tool Version 16.9.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.

Test run in progress...

Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-1234567890-AB", expectedResult: True)
Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-1234567890-XY", expectedResult: True)
Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-1234567890-A1", expectedResult: False)
Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-1234567890-A", expectedResult: False)
Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-123456789-AB", expectedResult: False)
Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-1234567890", expectedResult: False)
Passed!  - SpecialStringValidatorTests.SpecialStringValidatorTest(input: "1234567890-1234567890-ABCDE", expectedResult: False)

Test Run Successful.
Total tests: 7
     Passed: 7
 Total time: 1.7296 Seconds

التحقق المخصص وBlazor

والآن بعد أن علمت أنه يمكن استخدامه، من الواضح أنه من الجيد تنفيذه في Blazor، أليس كذلك؟

لنفترض أن لدي هذا النموذج، والذي سيستخدم النموذج Person الذي عرضته من قبل:

@using Models
@page "/"

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>

<EditForm Model=@Person FormName="PersonForm">
  <DataAnnotationsValidator/>
  <ValidationSummary/>
  <div class="form-group">
    <label for="Name">Name</label>
    <InputText @bind-Value=Person.Name class="form-control" id="Name" />
    <ValidationMessage For="() => Person.Name"/>
  </div>
  <div class="form-group">
    <label for="MySpecialString">My special string</label>
    <InputText @bind-Value=Person.MySpecialString class="form-control" id="Name" />
    <ValidationMessage For="() => Person.MySpecialString"/>
  </div>
  <div class="form-group">
    <label for="Age">Age</label>
    <InputNumber @bind-Value=Person.Age class="form-control" id="Age" />
    <ValidationMessage For=@(() => Person.Age) />
  </div>
  <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

@code {
  Person Person = new Person();
}

بمجرد تشغيل هذا، نحصل على الأخطاء التالية:

وإذا وضعنا ما نريد فقط، نحصل على الأمر التالي، كل شيء واضح:

لأكون صادقًا بالنسبة لي، من الواضح تمامًا أننا يجب أن ننقل المنطق على الأقل للتحقق من صحة هذه النماذج إلى سمات التحقق المخصصة، فهذا يمنحنا حرية تخزين الكود الخاص بتسجيل الدخول هذا في مكان واحد، ويمكننا استخدامه لاحقًا لواجهة برمجة التطبيقات (API) أو تطبيق آخر.

آمل أن تكون قد نالت إعجابك، إذا كان لديك أي أسئلة أو كنت ترغب في التواصل معي، فلا تتردد واتصل بي!