天天看點

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

簡要說明

【項目源碼】

【章節目錄】

本文主要介紹Automapper與Validation的使用方法。首先使用Automapper的目的是引入元件完成entity與dto之間的轉換以達到簡化代碼的目的。Abp vnext的項目中已經預設添加好此元件了【介紹】,本文隻是說一些簡單的用法,更進一步的使用需要到automapper的官網中檢視文檔

其次是Validation主要是用于入參校驗,通過對dto标注相應的屬性達到入參校驗的功能。【abp介紹】【官方介紹】

具體步驟

1、Automapper的基礎使用方法,在官方的文檔中也有比較清晰的說明,是以就隻是簡單的根據官方文檔寫一次。然後試運作一下簡單的效果即可。

添加相應的mapper使用的Dto,如UserDto,定義好可以對外輸出的屬性。

public class UserDto: EntityDto<Guid>
    {
        /// <summary>
        /// 使用者名稱
        /// </summary>
        public string user_name { get; set; }
        /// <summary>
        /// 使用者手機号
        /// </summary>
        public string user_phone { get; set; }
        /// <summary>
        /// 使用者狀态
        /// </summary>
        public int user_status { get; set; }
 
    }
           

其次在AbpVnext.Learn.Application中找到LearnApplicationAutoMapperProfile類,添加我們需要的mapper,

CreateMap<User, UserDto>();

最後在UserAppServices裡面添加以下代碼,其中ObjectMapper.Map就是轉換的方法。

public async Task<UserDto> LoginByUserPhoneAndPwd(string user_phone,string pass_word)
        {
            var user= await _repository.FindAsync(a=>a.user_phone== user_phone&&a.pass_word== pass_word&&a.user_status==0);
            return ObjectMapper.Map<User, UserDto>(user);
        }
           

調試代碼,輸出結果如下,轉換正常:

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

2、接下來主要介紹一下Validation的用法,官方的Validation是一個簡單與輕量化的元件,主要用資料注解的方式對入參字段的合法性校驗上。下面我們先來做一個簡單的例子,原來登入接口的入參的參數增加以下[Required]

/// <summary>
    /// 登入的Dto
    /// </summary>
    public class LoginDto:
    {
        /// <summary>
        /// 使用者手機号
        /// </summary>
        [Required]
        public string user_phone { get; set; }
        /// <summary>
        /// 登入密碼
        /// </summary>
        [Required]
        public string pass_word { get; set; }
    }
           

然後調試代碼,測試相應接口,如下圖抛出500異常,

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

再看日志,顯示的是校驗失敗異常,則表明我們的注解生效了。

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

3、上面雖然顯示我們的校驗生效了,但是輸出的結果明顯不是我們想要的結果。一般我們需要為校驗失敗的入參輸出統一的code和相應的字元串,讓我們的提示比較清晰明了,同時也讓前端開發的同僚比較明确的知道這個是由于參數校驗引起的問題,然後去修正相關參數。是以,我們需要替換掉abp的原有校驗異常輸出。

首先我們檢視官方文檔有說明,校驗異常統一為AbpValidationException 。

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

是以我們在原來的LeanGlobalExceptionFilter中攔截此類型的異常,并将輸出修改為code=100,如下:

public void OnException(ExceptionContext context)
        {
            logger.LogError(new EventId(context.Exception.HResult),
           context.Exception,
           context.Exception.Message);
            if (context.Exception is AbpValidationException)
            {
                context.Result = new JsonResult(new  { ode = 100, msg = context.Exception.Message });
            }
            else
            {
                context.Result = new JsonResult(new { code = 500, msg = "系統異常" });
            }
            context.ExceptionHandled = true;
        }
           

然後我們再來看看調試接口的輸出結果,如下,則表明我們的替換是成功了。

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

4、但是這樣就算成功了嗎?當然不是額,abp所有的校驗失敗輸出都是輸出這個:ModelState is not valid! See ValidationErrors for details.這樣的輸出,對我們前端或用戶端同僚是非常不友好的輸出,都不知道錯誤原因與相應的字段,是以我們需要進一步去優化這些資訊以達到最大程度的減少溝通成本的目的。下面我們來看看如何進行操作吧!

4.1、首先我們看一下注解裡面的ValidationAttribute,這個注解包含了字段ErrorMessage是用于輸出校驗錯誤的字段的,是以我們可以好好的利用一下這個ErrorMessage來達到我們的目的。把user_phone的[Required]修改成[Required(ErrorMessage ="手機号碼不能為空")]

4.2、我們回到LeanGlobalExceptionFilter這裡,看一下AbpValidationException裡面包含了什麼資訊。

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

如圖所示,我們看到了ValidationErrors這個字段是一個List,裡面包含了我們這一個請求入參的整個dto裡所有校驗不通過的資訊清單。這樣就好辦了,修改原來的攔截為以下代碼:

public void OnException(ExceptionContext context)
        {
            logger.LogError(new EventId(context.Exception.HResult),
           context.Exception,
           context.Exception.Message);
            if (context.Exception is AbpValidationException)
            {
                var validateerros = ((AbpValidationException)context.Exception).ValidationErrors;
                context.Result = new JsonResult(new  { ode = 100, msg = validateerros.Count > 0 ? validateerros[0].ErrorMessage : context.Exception.Message });
            }
            else
            {
                context.Result = new JsonResult(new { code = 500, msg = "系統異常" });
            }
            context.ExceptionHandled = true;
        }
           

然後調試代碼,并測試相應的接口。現在則表示顯示正常了。至于資訊到底是顯示第一個還是最後一個,自己判斷,個人感覺都可以,因為都屬于參數失敗的校驗

[Abp vNext 入坑分享] - 7.Automapper與validation的使用

4.3、接下來我們使用一下進階的判斷,脫離于單純的字段校驗,如:假如user_phone等于pass_word的時候抛出不能相等提示。這個需要dto繼承IValidatableObject然後增加Validate的實作方法,如下:

public IEnumerable<ValidationResult> Validate(
            ValidationContext validationContext)
        {
            if (user_phone == pass_word)
            {
                yield return new ValidationResult(
                    "手機号碼與密碼不能一樣!",
                    new[] { "user_phone", "pass_word" }
                );
            }
        }
           

然後調試代碼,并測試相應的接口,如下則表示替換成功了。。

[Abp vNext 入坑分享] - 7.Automapper與validation的使用