手把手教你AspNetCore WebApi:數據驗證


前言

小明最近又遇到麻煩了,小紅希望對接接口傳送的數據進行驗證,既然是小紅要求,那小明說什么都得滿足呀,這還不簡單嘛。

傳統驗證

[HttpPost]
public async Task<ActionResult<Todo>> PostTodo(Todo todo)
{
    if (string.IsNullOrEmpty(todo.Name))
    {
        return Ok("名稱不能為空");
    }
    context.Todo.Add(todo);
    await context.SaveChangesAsync();

    return CreatedAtAction("GetTodo", new { id = todo.Id }, todo);
}

小明寫着寫着發現這樣寫,很多接口相同得地方都要寫,使得代碼比較臃腫。

使用模型驗證

在參數模型上打上注解

namespace App001.Models
{
    /// <summary>
    /// 待辦事項
    /// </summary>
    public class Todo
    {
        /// <summary>
        /// ID
        /// </summary>
        public Guid Id { get; set; }
        /// <summary>
        /// 名稱
        /// </summary>
        [Required(ErrorMessage = "名稱不能為空")]
        public string Name { get; set; }
    }
}

Postman測試Name傳值未空時,則返回:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|df184e36-4e11844dfd38a626.",
    "errors": {
        "Name": [
            "名稱不能為空"
        ]
    }
}

注意Web API 控制器具有 [ApiController] 特性,則它們不必檢查ModelState.IsValid。在此情況下,如果模型狀態無效,將返回包含錯誤詳細信息的自動 HTTP 400 響應。

內置特性

  • [CreditCard]:驗證屬性是否具有信用卡格式。
  • [Compare]:驗證模型中的兩個屬性是否匹配。
  • [EmailAddress]:驗證屬性是否具有電子郵件格式。
  • [Phone]:驗證屬性是否具有電話號碼格式。
  • [Range]:驗證屬性值是否在指定的范圍內。
  • [RegularExpression]:驗證屬性值是否與指定的正則表達式匹配。
  • [Required]:驗證字段是否不為 null。
  • [StringLength]:驗證字符串屬性值是否不超過指定長度限制。
  • [Url]:驗證屬性是否具有 URL 格式。
  • [Remote]:通過在服務器上調用操作方法來驗證客戶端上的輸入。

Error messages

通過驗證特性可以指定要為無效輸入顯示的錯誤消息。 例如:

[Required(ErrorMessage = "名稱不能為空")]

使用自定義返回消息格式

有兩種方式:

  1. 使用自定義過濾器
  2. 使用默認模型驗證,需要在控制器上面加上【ApiController】。

使用自定義過濾器

首先,創建ModelValidateActionFilterAttribute過濾器。

public class ModelValidateActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            //獲取驗證失敗的模型字段
            var errors = context.ModelState
                .Where(e => e.Value.Errors.Count > 0)
                .Select(e => e.Value.Errors.First().ErrorMessage)
                .ToList();

            var str = string.Join("|", errors);

            //設置返回內容
            var result = new
            {
                Code = 10000,
                Msg = "未通過數據驗證。",
                FullMsg = str
            };

            context.Result = new BadRequestObjectResult(result);
        }

    }
}

然后,Startup.ConfigureServices將過濾器添加到控制器中並關閉默認模型驗證,另外我們還添加了AddNewtonsoftJson。

//關閉默認模型驗證
services.Configure<ApiBehaviorOptions>(opt => opt.SuppressModelStateInvalidFilter = true);
services.AddControllers(opt =>
{
    //添加過濾器
    opt.Filters.Add(typeof(ModelValidateActionFilterAttribute));
}).AddNewtonsoftJson(opt =>
{
    //json字符串大小寫原樣輸出
    opt.SerializerSettings.ContractResolver = new DefaultContractResolver();
});

最后,我們看一下返回效果:

{
    "Code": 10000,
    "Msg": "未通過數據驗證。",
    "FullMsg": "名稱不能為空。"
}

使用默認模型驗證

services.Configure<ApiBehaviorOptions>(opt =>
{
    opt.InvalidModelStateResponseFactory = actionContext =>
    {
        //獲取驗證失敗的模型字段 
        var errors = actionContext.ModelState
            .Where(e => e.Value.Errors.Count > 0)
            .Select(e => e.Value.Errors.First().ErrorMessage)
            .ToList();

        var str = string.Join("|", errors);

        //設置返回內容
        var result = new
        {
            Code = 10000,
            Msg = "未通過數據驗證。",
            FullMsg = str
        };

        return new BadRequestObjectResult(result);
    };
});

小結

目前為止,小明把數據驗證也搞定了,是不是so easy!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM