使用特性(Attribute)记录WebService的请求记录
背景:
项目架构是webservice做服务端,通过json来传递数据。前端有安卓、IOS、PHP几个团队。前端团队经常反馈遇到服务调用失败的情况,但是我们查看代码发现服务并没什么问题,所以经常会发生扯皮的情况,基于这个前提下,做一个记录前端请求的模块,记录前端请求的参数是否正确。
需求:
记录某些重要的请求的WebMethod及其请求的信息。
方案:
1.直接在每个WebMethod里修改,添加记录日志的代码
2.重写IHttpModule记录请求,自定义HttpApplication的BeginRequest事件记录日志。
3.添加全局应用程序记录请求,在Application_BeginRequest里记录日志。
4.使用特性,新增中间层继承ContextBoundObject,通过传递上下文来记录日志。
分析:
1.第1种需要改动现有的WebMethod,破坏原有结构。
2.第2种和第3种其实是一样的,都可以接收到所有的请求。
3.第4种非常灵活,可以在想要的WebMethod上添加,且不会修改到原有的逻辑。但是新增中间层传递上下文无疑是增加了结构发复杂性,考虑到现有项目已经比较大了,不想牵一发而动全身。
选择:
先定义一个用于标记是否需要写日志的特性,重写IHttpMoudule,拿到请求的文件及方法,通过反射判断该方法是否包含需要写日志的特性。
实现:
新增一个类RequestLogAttribute.cs继承Attribute,并且设置应用级别为方法。
[AttributeUsage(AttributeTargets.Method)]
public class RequestLogAttribute : Attribute { }新增一个类RequestLoggerHttpModule.cs继承IHttpModule,并实现Init方法。在Init方法中添加自定义事件HttpApplication.BeginRequest,可以拿到我们熟悉的HttpRequest、HttpContext、HttpResponse。
public class RequestLoggerHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
}
void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpContext context = application.Context;
HttpRequest request = application.Request;
HttpResponse response = application.Response;
}
public void Dispose(){}
}同时,在Web.Config里添加节点
<system.webServer> <modules> <add name="RequestLoggerHttpModule" type="命名空间.RequestLoggerHttpModule,程序集名"></add> </modules> </system.webServer>
有了HttpRequest之后,用反射拿到请求的方法,并且判断是否不是存在我们定义的特性。
#region 是否存在记录日志的特性
/// <summary>
/// 是否存在记录日志的特性
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
bool LogAttribute(HttpRequest request)
{
string extension = request.CurrentExecutionFilePathExtension;
if (string.IsNullOrEmpty(extension)) return false;
string filePath = request.FilePath.Replace(extension, string.Empty);
int last = filePath.LastIndexOf('/');//取最后一个/
filePath = filePath.Substring(last, filePath.Length - last);
string className = filePath.Replace("/", string.Empty);
string methodName = request.PathInfo.Replace("/", string.Empty);
Type t = Type.GetType(className);
if (t == null || string.IsNullOrEmpty(methodName)) return false;
MethodInfo method = t.GetMethod(methodName);
if (method == null) return false;
object[] attributes = method.GetCustomAttributes(typeof(RequestLogAttribute), false);
if (attributes == null || attributes.Length <= 0) return false;
return true;
}
#endregion所有请求的信息都包含在HttpRequest中,这个不再赘述。如有疑问可以参考:HttpRequest
使用方法也很简单
[WebMethod]
[RequestLog]
public void Test()
{
}

浙公网安备 33010602011771号