簡體   English   中英

web api 中 controller 級別的自定義驗證

[英]Custom validation at controller level in web api

我在網絡標准 2.0 庫中遇到了一個問題,我真的不知道如何解決它。

假設我有一個像這樣的 controller:

    [Route("{action}/{Id}")]
    [HttpPut]
    public void UpdateUser([FromBody] UserDTO user, long id )
    {
        _service.UpdateUser(user, id);
    }

很容易,它有效。 現在我想添加一些自定義驗證。 我知道我可以在 DTO 上使用System.ComponentModel.DataAnnotations ,但是當有錯誤請求時的消息是......錯誤。

我嘗試將ValidationAttributeisValidFormatErrorMessage一起使用,並將其添加到我的 controller 中,就像這樣

    [MyValidation]
    [Route("{action}/{Id}")]
    [HttpPut]
    public void UpdateUser([FromBody] UserDTO user, long id )
    {
        _service.UpdateUser(user, id);
    }

但它從未到達 MyValidation 代碼,它只是跳過了它。

有沒有辦法我可以做到這一點,以便我可以進行所有我想要的驗證並根據我的數據庫檢查它並做我需要的所有事情?

我該如何進行?

我找到的所有指南都與.core 或.mvc 有關,因為我在網絡標准庫上,所以我不能使用的東西即使是指南也會很棒:感謝任何想要幫助的人:D

我的解決方案!

所以,經過大量研究,我發現......這是不可能的。 至少根據我的理解/嘗試

我做了一些解決方法,因為我使用的東西不能在網絡標准庫上使用,無論如何,網絡標准似乎沒有這種東西可以使用。

我使用了 IActionFilter。

我創建了一個 class 並繼承了過濾器並放入了它需要的兩個方法,OnActionExecuted 和 OnActionExecuting。

public class UserFilter : IActionFilter
    {
       public void OnActionExecuted(ActionExecutedContext context)
        {
           
        }

      public void OnActionExecuting(ActionExecutingContext context)
        {
        }
    }

閱讀您可以使用的有效載荷中的內容

    UserDTO model = new UserDTO();
    model = context.ActionArguments["user"] as UserDTO;

其中 user 是您的有效負載的“名稱”。 要知道它是什么,您可以使用調試器並閱讀 context.actionArguments 中的內容。 請記住在該名稱之間使用“”。 您必須使用“as”關鍵字將其轉換為 model。 現在你可以訪問你的有效載荷,你可以做你自己的自定義驗證器!!!

在我的例子中,我創建了一個字符串列表,其中將包含字符串錯誤、驗證 id 並在列表至少包含一個元素時拋出錯誤。

例子:

     UserDTO model = new UserDTO();
     List<string> CustomError = new List<string>();
     model = context.ActionArguments["user"] as UserDTO;
     if (model.Age == 0) //dumb control, just for the sake of the example
        {
           CustomError.Add("age cannot be 0!")      
        }
     //other controls
     if (CustomError.Count > 0)
        {
            context.Result = new BadRequestObjectResult(CustomError);
        }

如果您創建的列表至少包含一個元素,則最后一個 if 很重要。 它會拋出一個錯誤的請求(錯誤 400),你會得到一個包含所有錯誤的 json。

在 controller 之上,您想要自定義驗證使用

     [HttpPost]
     [TypeFilter(typeof(UserFilter))]
     public IValidation<> PostUser(UserDTO user)
       {
        //your controller logic
       }

希望它會幫助將來像我一樣陷入困境的人,試圖以網絡標准自定義驗證數據,這似乎是不可能的

您需要實現 ValidationAttribute class,然后您可以編寫自己的邏輯並用作模型上的數據注釋。

示例實現

public class ValidJoinDate : ValidationAttribute
{      
    protected override ValidationResult 
            IsValid(object value, ValidationContext validationContext)
    {   
        DateTime _dateJoin = Convert.ToDateTime(value); 
        if (_dateJoin < DateTime.Now)
        {
            return ValidationResult.Success;
        }
        else
        {
            return new ValidationResult
                ("Join date can not be greater than current date.");
        }
    }        
}

並以這種方式在您的 model 屬性中使用:

public class Customer
{
    
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}"
        , ApplyFormatInEditMode = true)]
    [ValidJoinDate(ErrorMessage=
        "Join Date can not be greater than current date")] 
    public DateTime JoinDate { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = 
        "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [ValidLastDeliveryDate(ErrorMessage = 
        "Last Delivery Date can not be less than Join Date")]
    public DateTime LastDeliveryDate { get; set; }
   
}

希望這解決了你的問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM