影片講解
在新增的章節有提到過官方有內建一些常用的驗證標籤供我們使用,但有時候還是會碰上想在自己做一個更適合自己使用的驗證標籤,這時候就可以使用繼承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)
,這樣就大功告成了。
以上就是這篇的簡單示範,想看詳細操作的話可以看影片。
新手分享學習成果,若有錯誤,煩請告知修正,感謝🙏
範例檔:下載