請教大家都如何做 ModelBinding的驗證?
我的Model有一些代碼性質的欄位,想要在ModelBinding時跟資料庫的內容比對,驗證是否存在。
初步的想法是用ValidationAttribute
public class CustomValidationAttribute: ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
}
}
但接下去要怎麼做?我自已google 到一篇
https://andrewlock.net/injecting-services-into-validationattributes-in-asp-net-core/
他說可以這樣寫
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var service = (IExternalService) validationContext
.GetService(typeof(IExternalService));
// use service
}
但我自已試著寫了一個 IService,發現 service 永遠是 null.
是這個 service 需要特殊的寫法嗎?
或是這個思路就是不對的?
請大家給個建議。
Service不會憑空出現,必須經過Dependency Injection(簡稱DI)。 在ASP.NET Core的有提供基本的DI方法,讓你可以註冊需要的Service. 預設在Startup.cs, 裡面會有ConfigureServices方法做DI註冊, 之後不管是Constructor或Validation等, 背後DI會幫你把對應的Service物件注入.
可以參考MSDN的教學
.NET Core 中的相依性插入
而你找到這篇教學文的作者 Andrew Lock, 也是Manning出版的<ASP.NET Core In Action>的作者,裡面講解ASP.NET Core很詳細,推薦值得買來看。
MSDN的教學,對懂的人來說,是很有參考價值,但對不懂的人來說,就完全不知道在說什麼啊?
我現在的問題,已經在 Startup.cs 註冊這個 services 了,但是在 ValidatorAttributes 中 validationContext.GetService, 還是得到 null. 難道這個 Service 有特殊的要求(要特殊的寫法)嗎?
我有實際寫一遍, 可以取得到值, 可以參考看看~
所需的Service 和 ValidationAttribute
public class CustomValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var service = (IExternalService)validationContext
.GetService(typeof(IExternalService));
string s = service.GetValue();
return ValidationResult.Success;
}
}
public class ExternalService : IExternalService
{
public string GetValue()
{
return "Hello world";
}
}
public interface IExternalService
{
string GetValue();
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient(typeof(IExternalService), typeof(ExternalService));
}
Controller.cs
[HttpGet]
public IEnumerable<WeatherForecast> Get([FromQuery]MyInputVM myInputVM)
{
/// 某程式碼
}
MyInputVM.cs
public class MyInputVM
{
[CustomValidation]
public string S { get; set; }
}
在service.GetValue()我能取的到值 "Hello world"
版本是ASP.NET Core 3.1
原來是我自已搞烏龍。我的方案有2個專案,A專案參考B專案,我應該要在A專案的Startup註冊service,結果我一直弄到B專案的Startup,難怪都會失敗。
恭喜呀XD 有找到問題~