自從學會Self-Hosting ASP.NET Web API,遇到Console Application/Window Form/WPF程式需提供API介面的場合,我都二話不說召喚它出來打怪,開開心心地在EXE裡寫Web,好不快意~
最近有個情境,需要為Web API保留存取Log記錄,查了一下,HttpSelfHostServer似乎沒提供內建的Logging機制。沒想太多,決定利用MessageHandler配合NLog自己寫一個。
LogHandler只需繼承DelegatingHandler實作SendAsync(),攔截Request及Reponse輸出到NLog,程式碼不多:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.ServiceModel.Channels;
using System.Text;
using NLog;
namespace MySelfHostWebApi
{
publicclass LogHandler : DelegatingHandler
{
privatestatic Logger logger = NLog.LogManager.GetCurrentClassLogger();
//REF: http://blog.kkbruce.net/2012/05/aspnet-web-api-8-http-http-message.html
protectedoverride System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
System.Threading.CancellationToken cancellationToken)
{
//取得Method、IP、Url等等,稍後寫入NLog
string method = request.Method.ToString();
//REF: http://bit.ly/16lpGKM
//在Self-Hosted模式,透過RemoteEndpointMessageProperty取得IP
string ip = "Unknown";
if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
ip = ((RemoteEndpointMessageProperty)
request.Properties[RemoteEndpointMessageProperty.Name]).Address;
string url = request.RequestUri.ToString();
returnbase.SendAsync(request, cancellationToken)
.ContinueWith((task) =>
{
//Response回傳時,連同StatusCode一起寫入NLog
HttpResponseMessage resp = task.Result as HttpResponseMessage;
logger.Log(LogLevel.Trace, string.Format("{0} {1} {2} {3}",
ip, method, url, (int)resp.StatusCode));
return resp;
});
}
}
}
使用方法很簡單,將LogHandler加進HttpSelfHostConfiguration.MessageHandlers,再設妥NLog.config,就大功告成囉!
//設定路由
config.Routes.MapHttpRoute("API",
"{id}",
new {
controller = "download",
action = "index"
});
//加上LogHandler,記錄存取Log
config.MessageHandlers.Add(new LogHandler());
httpServer = new HttpSelfHostServer(config);
記錄的Log檔範例如下:
2013-08-01 05:14:46.4144 192.168.1.5 GET httq://192.168.1.1:4567/test.jpg 404
2013-08-01 05:18:15.9233 192.168.1.18 GET httq://192.168.1.1:4567/66fd.png 200
【延伸閱讀】