說到AOP編程,可能大部分人是即熟悉又顯得陌生。
AOP的作用就是橫切關注點,然後將分離後的關注點以面的形式來呈現,這是概念性的說法,舉個列子來說明吧。
比如說有個API接口處理場景是提交訂單,在我們提交訂單的時候,首先客戶端要對用戶提交的數據進行合法性驗證,驗證通過後,數據發送到服務端,因客戶端一切操作都是不可信的,必然服務端在錄入訂單信息之前也需要對數據合法性進行驗證。
針對上述問題我們可以這樣子來編碼
首先定義訂單表單參數實體對象:
1 /// <summary> 2 /// Post表單參數 3 /// </summary> 4 public class FromOrderInfo 5 { 6 /// <summary> 7 /// 商品名稱 8 /// </summary> 9 public string ShopName { get; set; } 10 /// <summary> 11 /// 手機號 12 /// </summary> 13 [ValidateMobile(ErrorMessage = "請輸入正確格式的手機號")]//自定義驗證規則 14 public string Mobile { get; set; } 15 /// <summary> 16 /// Address 17 /// </summary> 18 [ValidateMaxLength(20,ErrorMessage = "Address字符超過指定長度")] 19 public string Address { get; set; } 20 }
自定義驗證如下:
/// <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接口:
[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
定義過濾器:
/// <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
實體對像屬性驗證類:
/// <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接口
感謝您的閱讀!