程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 如何在WebApi中使用過濾器實現面向切面編程(AOP)

如何在WebApi中使用過濾器實現面向切面編程(AOP)

編輯:關於.NET

     說到AOP編程,可能大部分人是即熟悉又顯得陌生。

    AOP的作用就是橫切關注點,然後將分離後的關注點以面的形式來呈現,這是概念性的說法,舉個列子來說明吧。

     比如說有個API接口處理場景是提交訂單,在我們提交訂單的時候,首先客戶端要對用戶提交的數據進行合法性驗證,驗證通過後,數據發送到服務端,因客戶端一切操作都是不可信的,必然服務端在錄入訂單信息之前也需要對數據合法性進行驗證。

    針對上述問題我們可以這樣子來編碼

    首先定義訂單表單參數實體對象:

 

 /// <summary>
    /// Post表單參數
    /// </summary>
    public class FromOrderInfo
 5     {
        /// <summary>
        /// 商品名稱
        /// </summary>
        public string ShopName { get; set; }
        /// <summary>
        /// 手機號
        /// </summary>
        [ValidateMobile(ErrorMessage = "請輸入正確格式的手機號")]//自定義驗證規則
        public string Mobile { get; set; }
        /// <summary>
        /// Address
        /// </summary>
        [ValidateMaxLength(20,ErrorMessage = "Address字符超過指定長度")]
        public string Address { get; set; }
20     } 
 

 在表單對象FromOrderInfo實體類裡面有ValidateMobile和ValidateMaxLength驗證類

接下來我們需要編寫自定義ValidateMobile和ValidateMaxLength驗證類

自定義驗證如下:

 /// <summary>
     /// 驗證字符長度是否超過指定長度
     /// </summary>
     public class ValidateMaxLengthAttribute : ValidationAttribute
     {
         private readonly int MaxLength;
 
         public ValidateMaxLengthAttribute(int maxLength)
             : base("{0}的字符太多了!")
         {
             MaxLength = maxLength;
         }
 
         protected override ValidationResult IsValid(object value, ValidationContext validationContext)
         {
             if (value != null)
             {
                 string content = value.ToString();
                 int leng = StringTool.GetStringLength(content);
                 if (leng > MaxLength)
                 {
                     string errorMessage = FormatErrorMessage(validationContext.DisplayName);
                     return new ValidationResult(errorMessage);
                 }
             }
             return ValidationResult.Success;
         }       
     }
 
 /// <summary>
    /// 驗證手機號
    /// </summary>
    public class ValidateMobileAttribute : ValidationAttribute
     {
        public ValidateMobileAttribute()
             : base("{0}應輸入11位手機號!")
         {
         }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                string content = value.ToString();
                if (!RegexTool.IsMobile(content))
                {
                    string errorMessage = FormatErrorMessage(validationContext.DisplayName);
                    return new ValidationResult(errorMessage);
                }
            }
            return ValidationResult.Success;
        }
     }
View Code

 

表單參數和自定義驗證類完成了,接下來就是用戶提交訂單,就需要請求API接口。
訂單API接口代碼如下:

 [CHKFormInput(typeof(FromOrderInfo))]
         public HttpResponseMessage TestOrder([FromBody] FromInfo info)
         {
             var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK);
 
             challengeMessage = new ResponseMessage<string>("json").Response("下單成功");
             return challengeMessage;
 
         }
 
 /// <summary>
     /// Post表單參數
     /// </summary>
     public class FromInfo
     {
         /// <summary>
         /// Json數據對象
         /// </summary>
         public string JsonFormat { get; set; }
     }
View Code

 


因API接口中POST請求只能用[FromBody]來包含,所以我們需要把表單參數轉換成Json格式的字符串,用JsonFormat 來接收。。。

 接下來就是編寫CHKFormInput過濾器,在進入之前Action之前對表單參數進行攔截驗證。

定義過濾器代碼:
 /// <summary>
     /// 驗證表單參數
     /// </summary>
 public class CHKFormInput : ActionFilterAttribute
     {
         private Type _type;
         /// <summary>
         /// 構造函數
         /// </summary>
         /// <param name="type">表單參數驗證對象</param>
         public CHKFormInput(Type type = null)
         {
             if (type != null)
             {
                 this._type = type;
             }
         }
         public override void OnActionExecuting(HttpActionContext actionContext)//執行action動作所需執行的操作
         {
             #region 檢查表單參數是否合法
             var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK);
             ErrorResponse errorMsgConvertjson = new ErrorResponse();//返回錯誤信息string errorMsg = string.Empty;
             try
             {
                 if (actionContext == null)
                 {
                     throw new System.Web.Http.HttpResponseException(challengeMessage);
                 }
                 if (ProjectRequest.IsPost())//驗證是否POST請求
                 {
                     var task = actionContext.Request.Content.ReadAsStreamAsync();
                     var content = string.Empty;
                     using (System.IO.Stream sm = task.Result)
                     {
                         if (sm != null)
                         {
                             sm.Seek(0, SeekOrigin.Begin);
                             int len = (int)sm.Length;
                             byte[] inputByts = new byte[len];
                             sm.Read(inputByts, 0, len);
                             sm.Close();
                             content = Encoding.UTF8.GetString(inputByts);
                         }
                     }
                     var m = JsonTool.JsonToEntity<FromInfo>(content);
                     var Json = Serializer.Deserialize(m.JsonFormat, _type);
                     new TryValidateModelTool().TryValidateModel(Json, ref errorMsg);
                     if(!string.IsNullOrEmpty(errorMsg))
                     {
                         errorMsgConvertjson.Message = errorMsg;
                         errorMsgConvertjson.State = CallBackServer.InputError;
                         challengeMessage = new ResponseMessage<ErrorResponse>("json").Response(errorMsgConvertjson);
                         actionContext.Response = challengeMessage;
                     }
                     
                 }
                 
             }
             catch (Exception ex)
             {
             }
             finally
             {
             }
             base.OnActionExecuting(actionContext);
             #endregion
         }
     }
View Code

 



定義了過濾器後,我們如何把截取到的FromOrderInfo表單參數來進行驗證呢?

  然後我們還需要繼續編寫一個類來執行附加在實體屬性的驗證規則

實體對像屬性驗證類:


 /// <summary>
     /// 利用特性驗證實體對象參數合法性
     /// </summary>
     public class TryValidateModelTool : ApiController
     {
         /// <summary>
         /// 利用特性驗證實體對象參數合法性
         /// </summary>
         /// <param name="model">對象</param>
         /// <param name="errorMsg">錯誤信息</param>
         /// <returns></returns>
         public bool TryValidateModel(object model, ref string errorMsg)
         {
             return TryValidateModel(model, null /* prefix */, ref errorMsg);
         }
 
         
 
 
         /// <summary>
         /// 利用特性驗證實體對象參數合法性
         /// </summary>
         /// <param name="model">對象</param>
         /// <param name="errorMsg">錯誤信息</param>
         /// <returns></returns>
         public bool TryValidateModel(object model, string prefix, ref string errorMsg)
         {
             if (model == null)
             {
                 throw new ArgumentNullException("model");
             }
 
             ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
             var t = new ModelBindingExecutionContext(new HttpContextWrapper(HttpContext.Current), new System.Web.ModelBinding.ModelStateDictionary());
             List<string> errorMsgList = new List<string>();
             foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(metadata, t).Validate(null))
             {
                 ModelState.AddModelError(validationResult.MemberName, validationResult.Message);
                 errorMsgList.Add(validationResult.Message);
             }                       
             errorMsg = string.Join(",", errorMsgList);
             return ModelState.IsValid;
         }
     }
View Code

 

 

至此整個AOP過濾器編碼全部完成,在用戶提交表單之前,API接口會首先進入CHKFormInput 過濾器驗證參數合法性,如驗證失敗,將不進入提交訂單的API接口

感謝您的閱讀!
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved