在前一篇文章[.NET] 在WebAPI中使用AOP的方式,控制器中加入Attribute集中進行例外狀態的處理中
說明了如何透過AOP的方式攔截Exception的方式,當然也可以透過AOP的處理,來寫入Log的內容
這篇文章中,會說明了如何在控制器中加入一個Attribute,就可以把在控制器中的輸入與輸出完全寫入至Log中
要在控制器中加入對應的Attribute,並直接將輸入與輸出的參數寫入至Log,這個功能製作起來非常的簡單
首先先在WebAPI的專案中加入一個類別庫LogHandle.cs
接著將下面的程式碼加入至該類別庫中
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.IO;
using Newtonsoft.Json;
/// <summary>
/// 進行Log處理的類別物件
/// </summary>
public class LogHandle : ActionFilterAttribute
{
/// <summary>
/// 實際寫入Log的動作
/// </summary>
/// <param name="strAction">動作類別字串</param>
/// <param name="strContent">寫入Log的內容</param>
private void WriteLogContent(string strAction, string strContent)
{
string strLineContent = DateTime.Now.ToString("yyyyMMdd HH:mm:ss") + " Type:" + strAction + " Content:" + strContent;
File.AppendAllLines(@"D:\Log\File.txt", new string[] { strLineContent });
}
}
在這個LogHandle.cs的類別庫中,讓LogHandle繼承ActionFilterAttribute這個物件,並覆寫OnActionExecuting與OnActionExecuted這兩個事件
/// <summary>
/// 當WebAPI的控制器剛被啟動的時候,會進入至這個覆寫的事件中
/// </summary>
/// <param name="actionContext"></param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
// 因為傳入的參數為多數,所以ActionArguments必須用迴圈將之取出
foreach (var item in actionContext.ActionArguments)
{
// 取出傳入的參數名稱
string strParamName = item.Key;
// 取出傳入的內容並作Json資料的處理
string strContent = strParamName + ":" + JsonConvert.SerializeObject(item.Value);
// 寫入Log
this.WriteLogContent("Input", strContent);
}
}
OnActionExecuting的事件,主要是發生在當WebAPI被呼叫,且一進入控制器中的Action時會引發的事件,所以在這個事件裡,透過迴圈的方式,將傳入的參數與資料取出後,並寫入Log之中
/// <summary>
/// 當WebAPI的控制器結束動作,會進入這個覆寫的事件中
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
// 將actionExecutedContext.Response.Content轉換成Json的字串
string strResponseContent = JsonConvert.SerializeObject(actionExecutedContext.Response.Content);
// 將Json字串轉換成我們自訂的ResponseContentModel物件
ResponseContentModel objResponseContent = JsonConvert.DeserializeObject<ResponseContentModel>(strResponseContent);
// 取出從WebAPI回傳的物件,並轉會成Json字串
string strContent = JsonConvert.SerializeObject(objResponseContent.Value);
// 寫入Log
this.WriteLogContent("Output", strContent);
}
OnActionExecuted的事件,則是發生在將值return出WebAPI的事件之後,也就是當這個Action結束時引發的,而在這個事件中,透過JsonConvert的方式,將Response.Content的內容轉換成字串,再轉出成為我們需要的物件,因為Response的內容很多,但是如果我們只想要將最後回傳的內容寫入到Log的話,就必須取出Response.Content.Value這個物件,所以不得不透過這樣的方式將值作取得。
當然,取得之後,就可以透過寫入Log的副程式寫入Log
接著,我們加入一個新的控制器,並命名為LogSample
接著我們在LogSample裡,加入一個簡單的Post事件
[HttpPost]
[ActionName("WriteLogSample")]
[LogHandle]
public WriteLogSampleResultModel Post(WriteLogSampleModel value)
{
// 在這裡處理一些事,然後return物件
WriteLogSampleResultModel objResult = new WriteLogSampleResultModel()
{
IsGet = true,
Message = "我收到你的資料了",
};
return objResult;
}
public class WriteLogSampleModel
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime Birthday { get; set; }
}
/// <summary>
/// 輸出WebAPI的物件模型
/// </summary>
public class WriteLogSampleResultModel
{
public bool IsGet { get; set; }
public string Message { get; set; }
}
這個Action中,傳入了一個我們自訂的物件WriteLogSampleModel,並回傳了WriteLogSampleResultModel物件
接下來,就可以實際執行一下這個WebAPI的功能了,下圖是透過Postman呼叫WebAPI的動作,可以看到這個WebAPI是有正確回傳我們要的結果的
最後,我們打開在WriteLogContent這個副程式裡,寫入指定路徑的Log檔內容,可以看到傳入WebAPI的參數物件,以及要回傳出WebAPI的物件內容都有被正確的寫入到Log檔之中了
透過AOP的方式,採用ActionFilterAttribute的處理,可以在最小幅度改寫現有程式的情況下,取得在WebAPI中Request以及Response的內容,並寫入至所需的位置、儲存體或是資料庫,是個非常便利的處理方式。