7-4.ASP.NET Core MVC 入門教學 - 類別內自訂屬性資料驗證

ASP.NET Core MVC 入門教學

前幾節課我們都是使用標籤來做驗證,但很多時候我並不想多寫這麼多單一用途的標籤

這時候我們就可以直接寫在該Dto裡面

其實有人可能會把驗證邏輯跟商業邏輯寫在一起,但這樣的做法並不好,會顯得程式很雜亂

所以寫到Dto裡是非常適合的地方,以後想找有關資料欄位的事情,就是打開Dto就對了

public class NewsCreateDto : IValidatableObject
{
    [Required(ErrorMessage = "標題不可為空")]
    public string Title { get; set; }

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

    public int DepartmentId { get; set; }

    public DateTime StartDateTime { get; set; }

    public DateTime EndDateTime { get; set; }

    public List<IFormFile> Files { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        KcgContext _kcgContext = (KcgContext)validationContext.GetService(typeof(KcgContext));

        var findTitle = from a in _kcgContext.News
                        where a.Title == Title
                        select a;

        if (findTitle.FirstOrDefault() != null)
        {
            yield return new ValidationResult("已存在相同的新聞標題");
        }

        if (StartDateTime > EndDateTime)
        {
            yield return new ValidationResult("開始日期不可大於結束日期");
        }
    }
}

就如上面的程式碼,我們將標題跟日期的驗證都搬來NewsCreateDto裡面,當然要額外繼承一個IValidatableObject

接著其他的用法都跟自訂標籤的寫法一樣,唯一不同的是回傳的部分要用yield return

因為這邊是可以回傳複數的驗證結果,所以要用yield

接著我們看結果

不過出現的位置似乎不理想,在最上方綜合驗證的地方,所以我們可以改一下,想出現在個別欄位的地方

yield return new ValidationResult("已存在相同的新聞標題", new[] { nameof(Title) });
yield return new ValidationResult("開始日期不可大於結束日期", new[] { nameof(StartDateTime) });

如此就可以出現在該欄位的下方,而不是最上方

但這樣一來,如果我也想要同樣規則套用在修改的Dto上,不就要寫兩個地方,沒辦法共用了?

這其實可以用抽象化的方式來去寫,就可以不用同時維護兩個地方增加麻煩,如果有人想知道怎麼寫可以留言,或者以後有機會會再提到

 

範例檔:下載




Copyright © 凱哥寫程式 2022 | Powered by TalllKai ❤