ASP.NET Core Web API 入門教學 - 自訂模型資料驗證標籤


Posted by TalllKai on 2021-06-20

影片講解:


在新增的章節有提到過官方有內建一些常用的驗證標籤供我們使用,但有時候還是會碰上想在自己做一個更適合自己使用的驗證標籤,這時候就可以使用繼承ValidationAttribute來打造專屬自己的驗證標籤。

首先先創一個ValidationAttributes資料夾來放自訂的驗證標籤,然後我們取名為TodoNameAttribute。

接著寫上我們的基本外框。

public class TodoNameAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
    }
}

繼承ValidationAttribute,並且裡面有一個override ValidationResult的方法,這是我們今天要寫判斷邏輯的地方。

接著要來示範,如果我今天想從資料庫驗證,這一個代辦事項(Name欄位),有沒有存在,那該如何實作呢,會舉這個例子,是想順便教說如何在這裡取得資料庫連線物件(或其他DI注入的服務)。

我們可以透過ValidationContext來取得相關service。

TodoContext _todoContext = (TodoContext)validationContext.GetService(typeof(TodoContext));

接著我們就來寫相關判斷邏輯,以下為完整程式碼。

public class TodoNameAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        TodoContext _todoContext = (TodoContext)validationContext.GetService(typeof(TodoContext));

        var name = (string)value;

        var findName = from a in _todoContext.TodoLists
                       where a.Name == name
                       select a;

        if (findName.FirstOrDefault() != null)
        {
            return new ValidationResult("已存在相同的代辦事項");
        }

        return ValidationResult.Success;
    }
}

一開始我們從object value取到的值會是你驗證標籤所放置的欄位的值,因為我們預定會放在name上,所以會是個string,接著我們再去資料庫撈有沒有相同的name,最後如果findName != null就代表資料庫有相同的name,那我們就回傳一個錯誤訊息,如果找不到則會執行ValidationResult.Success代表我們通過驗證。

接著我們把寫好的標籤放在TodoListPostDto.cs的Name上方

public class TodoListPostDto
{
    [TodoName]
    public string Name { get; set; }
}

然後我們馬上來測試效果如何,新增一筆資料庫已存在的去上課的資料。

這時候就可以看到結果回應我們"已存在相同的代辦事項",代表驗證程式有如期的運作。

但這時候如果我們要放在TodoListPutDto.cs的Name上可能就會有一些小問題,什麼樣的問題?就是我們今天可能在做修改時,Name並不改動而是改其他欄位,那我們上方的判斷邏輯,就會抓到自己這筆而導致驗證不過,所以我們要修改一下。

public class TodoNameAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        TodoContext _todoContext = (TodoContext)validationContext.GetService(typeof(TodoContext));

        var name = (string)value;

        var findName = from a in _todoContext.TodoLists
                       where a.Name == name
                       select a;

        var dto = validationContext.ObjectInstance;

        if (dto.GetType() == typeof(TodoListPutDto))
        {
            var updateDto = (TodoListPutDto)dto;
            findName = findName.Where(a => a.TodoId != updateDto.TodoId);
        }

        if (findName.FirstOrDefault() != null)
        {
            return new ValidationResult("已存在相同的代辦事項");
        }

        return ValidationResult.Success;
    }
}

一開始我們先從validationContext.ObjectInstance可取得整個類別,接著我們再判斷我們是進到哪個類別,這邊的話就是如果是dto.GetType() == typeof(TodoListPutDto),代表我們當下是做更新,這裡也可以表現出為什麼我們必須將新增和修改拆成兩個Dto的原因之一,因為我們可能會有很多判斷是不一樣的。

確定是更新的時候,我們就再排除自己的todoid,findName = findName.Where(a => a.TodoId != updateDto.TodoId),這樣就大功告成了。

以上就是這篇的簡單示範,想看詳細操作的話可以看影片。

新手分享學習成果,若有錯誤,煩請告知修正,感謝🙏

範例檔:下載


#ASP.NET Core #Web API #.NET 5







Related Posts

初心者的計概--SESSION 與 COOKIE

初心者的計概--SESSION 與 COOKIE

Jest 自己的程式自己測試

Jest 自己的程式自己測試

Day 71

Day 71


Comments