使用特性(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()
        {
        }


原文地址:https://www.cnblogs.com/wugang/p/14232327.html