說到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接口
感謝您的閱讀!