在 ValidationAttribute 如何使用 Microsoft.Extensions.DependencyInjection Container 的物件

ValidationAttribute 可以讓我們自訂驗證邏輯,搭配 ValidationContext 就可以驗證整個 Model 的狀態,詳情請參考 [Validation] 自訂模型驗證 | 余小章 @ 大內殿堂 - 點部落 (dotblogs.com.tw)

當 ValidationAttribute 依賴其他的物件時,為了有效管理資源,除了使用靜態成員之外,我們還可以透過 DI Container 來取得其他物件。

開發環境

  • Windows 10
  • .NET 5

在 Property 上面掛上 Attribute 就可以完成驗證了

private class Model
{
	[Required]
	[StringLength(10)]
	public string Id { get; set; }
}

實作

在 ValidationAttribute 取出依賴物件的時候有以下幾種做法

  1. 從賴靜態成員取出依賴物件
  2. 使用 DI Container 取出依賴物件

從賴靜態成員取出依賴物件

internal class InstanceManager
{
	private static Model s_type;

	public static Model Type
	{
		get
		{
			if (s_type == null)
			{
				s_type = new Model();
			}

			return s_type;
		}
		set => s_type = value;
	}
}

 

在 ValidationAttribute 依賴InstanceManager.Type

public class IdAttribute : ValidationAttribute
{
	protected override ValidationResult IsValid(object instance,
												ValidationContext validationContext)
	{
		var model = InstanceManager.Type;

		var validationResult = ValidationResult.Success; 
		... 驗證邏輯 
		return validationResult;
	}
}

 

從 DI Container 取出依賴物件

ValidationContext.GetService 可以取出容器裡的物件

public class IdAttribute : ValidationAttribute
{
	protected override ValidationResult IsValid(object instance,
												ValidationContext validationContext)
	{
		var model = validationContext.GetService<Model>();

		var validationResult = ValidationResult.Success; 
		... 驗證邏輯 
		return validationResult;
	}
}

 

在 ASP.NET / ASP.NET Core 框架生命週期,當 Request 給 ASP.NET 伺服器時其中有一段 Filter 是用來做 Molde Binding 和 Validate,應該都能透過 ValidationContext.GetService 取得 DI Container 的物件。

如果是在非 ASP.NET / ASP.NET Core,在調用端我們也可以透過 ValidationContext + Validator  來完成驗驗

var context = new ValidationContext(instance, null, null);
var errors = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(instance, context, errors, true);

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo