iT邦幫忙

0

[c# webapi] 自訂驗證怎麼寫?

請教大家都如何做 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 需要特殊的寫法嗎?
或是這個思路就是不對的?
請大家給個建議。

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
glj8989332
iT邦研究生 4 級 ‧ 2020-07-18 17:13:15
最佳解答

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很詳細,推薦值得買來看。

看更多先前的回應...收起先前的回應...
Brandon iT邦新手 4 級 ‧ 2020-07-18 22:13:25 檢舉

MSDN的教學,對懂的人來說,是很有參考價值,但對不懂的人來說,就完全不知道在說什麼啊?/images/emoticon/emoticon02.gif

我現在的問題,已經在 Startup.cs 註冊這個 services 了,但是在 ValidatorAttributes 中 validationContext.GetService, 還是得到 null. 難道這個 Service 有特殊的要求(要特殊的寫法)嗎?

glj8989332 iT邦研究生 4 級 ‧ 2020-07-18 23:33:44 檢舉

我有實際寫一遍, 可以取得到值, 可以參考看看~

所需的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

Brandon iT邦新手 4 級 ‧ 2020-07-19 23:29:19 檢舉

原來是我自已搞烏龍。我的方案有2個專案,A專案參考B專案,我應該要在A專案的Startup註冊service,結果我一直弄到B專案的Startup,難怪都會失敗。

glj8989332 iT邦研究生 4 級 ‧ 2020-07-19 23:45:34 檢舉

恭喜呀XD 有找到問題~

我要發表回答

立即登入回答