zoukankan      html  css  js  c++  java
  • 接口调优——WebAPI 过滤器,IIS WebDAV

    目录

    本周工作的时候,任务计划已经完成,进行了接口的调优,其中对于过滤器这一块着重进行了调整。

    在这个过程中对过滤器的顺序有了一定了解,这里记录下来。

    1、身份认证过滤器—AuthenticationFilter

    这个是做统一身份认证授权的,这个是最先进来的,进行用户身份验证:

    public class BasicAuthenticationFilterAttribute : FilterAttribute, IAuthenticationFilter
        {
            public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
            {
                if (context.ActionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
                {
                    return Task.FromResult(0);
                }
    
                 // 具体认证业务逻辑
            }
    
            public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
            {
                string realm = context.Request.RequestUri.DnsSafeHost;
                context.Result = new AddBasicChallengeResult(context.Result, realm);
                return Task.FromResult(0);
            }
    
            // 错误信息生成
            public class AuthenticationFailureResult : IHttpActionResult
            {
                public AuthenticationFailureResult(HttpRequestMessage request)
                {
                    Request = request;
                }
    
                public HttpRequestMessage Request { get; private set; }
    
                public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
                {
                    return Task.FromResult(Execute());
                }
    
                private HttpResponseMessage Execute()
                {
                    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
                    {
                        RequestMessage = Request
                    };
                    return response;
                }
            }
    
            // 认证失败返回质询信息
            private class AddBasicChallengeResult : IHttpActionResult
            {
                private IHttpActionResult innerResult;
                private string realm;
    
                public AddBasicChallengeResult(IHttpActionResult innerResult, string realm)
                {
                    this.innerResult = innerResult;
                    this.realm = realm;
                }
    
                public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
                {
                    var response = await innerResult.ExecuteAsync(cancellationToken);
                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                        response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic", String.Format("realm="{0}"", realm)));
                    return response;
                }
            }
        }

    2、Action 过滤器—ActionFilter

    这个是对操作进行统一过滤的过滤器,在这个过滤器里面可以做的事情就很多,我们这里用到了:模型验证、请求信息记录、返回信息格式化;

    在这里就分别说下几个具体的业务逻辑;

    A、请求信息记录—RequestLogFilter

    这里的记录接口请求信息,记录下每个接口请求详情,便于查看记录,具体代码:

    public class RequestLogFilterAttribute : ActionFilterAttribute
        {
            private readonly string Key = "_RequestTime_";
            private readonly string Watch = "_Stopwatch_";
            private readonly string Token = ConfigurationManager.AppSettings["Token"].ToString();
    
            public override void OnActionExecuting(HttpActionContext actionContext)
            {
                base.OnActionExecuting(actionContext);
    
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
                actionContext.Request.Properties[Key] = DateTime.Now;
                actionContext.Request.Properties[Watch] = stopWatch;
            }
    
            public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
            {
                Stopwatch stopWatch = actionExecutedContext.Request.Properties[Watch] as Stopwatch;
                stopWatch.Stop();
    
                // 如果有该特性就不记录请求记录(绕过记录)
                if (actionExecutedContext.ActionContext.ActionDescriptor.GetCustomAttributes<BypassRequestLogFilterAttribute>().Any())
                {
                    return;
                }
    
    
                // 具体记录接口请求信息
            }
        }

    B、模型验证—ValidateModelFilter

    这个是模型验证的,对接口的数据有效性进行验证

    public class ValidateModelFilterAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(HttpActionContext actionContext)
            {
                if (actionContext.ModelState.IsValid == false)
                {
                    List<Dictionary<string, string>> allErrors = new List<Dictionary<string, string>>();
                    var modelState = actionContext.ModelState;
                    foreach (var key in modelState.Keys)
                    {
                        Dictionary<string, string> errorDictionary = new Dictionary<string, string>();
                        var state = modelState[key];
                        string[] errorMessages = state.Errors.Select(t => t.ErrorMessage).ToArray();
                        errorDictionary.Add(key, string.Join(",", errorMessages));
    
                        allErrors.Add(errorDictionary);
                    }
    
                    ResponseData responseData = new ResponseData { MsgCode = 1, Message = "参数有误!", Data = allErrors };
                    JsonMediaTypeFormatter jsonMediaTypeFormatter = actionContext.Request.GetConfiguration().Formatters.JsonFormatter;
    
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, responseData, jsonMediaTypeFormatter);
                }
            }
        }

    C、返回信息格式化—ResponseFormatterFilter

    之所以添加这个过滤器是在我们手机端调用接口的时候,发现返回的信息不是定义好的,

    是经过了一种格式化,不能按照我们既定的格式进行解析(分析发现,是请求的时候格式化,返回的信息也按照这个格式化),

    所以在过滤器里再对全部的返回信息进行格式化:

    public class ResponseFormatterFilterAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
            {
                if (actionExecutedContext.Response != null && actionExecutedContext.Response.IsSuccessStatusCode)
                {
                    ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
                    JsonMediaTypeFormatter jsonMediaTypeFormatter = actionExecutedContext.Request.GetConfiguration().Formatters.JsonFormatter;
    
                    actionExecutedContext.Response = new HttpResponseMessage
                    {
                        StatusCode = HttpStatusCode.OK,
                        Content = new ObjectContent(content.Value.GetType(), content.Value, jsonMediaTypeFormatter)
                    };
                }
            }
        }

    这几个都是继承自:ActionFilterAttribute,为了比较清晰所以分开放。

    对于这种同一级别的过滤器,其执行的先后顺序是:注册在前的先进后出,注册在后的后进先出(大致如下图)

    3、异常处理过滤器—ExceptionFilterAttribute

    这个是统一处理有异常的过滤器,多错误过滤,返回给客户端的是处理过的,也是最后面一个出去的,过滤器里面有错误也会捕捉到。

    具体代码:

    public class ExceptionLogFilterAttribute : ExceptionFilterAttribute
        {
            public override void OnException(HttpActionExecutedContext actionExecutedContext)
            {
                base.OnException(actionExecutedContext);
    
                JsonMediaTypeFormatter jsonMediaTypeFormatter = actionExecutedContext.Request.GetConfiguration().Formatters.JsonFormatter;
                ResponseData responseData;
    
                if (actionExecutedContext.Exception is ExceptionEx)
                {
                    responseData = new ResponseData { MsgCode = 1, Message = actionExecutedContext.Exception.Message };
                }
                else
                {
                    Exception exceptionData = null;
    
                    if (ConfigurationManager.AppSettings["ApplicationEnvironment"] == ApplicationEnvironmentEnum.Development.ToString())
                    {
                        exceptionData = actionExecutedContext.Exception;
                    }
    
                    responseData = new ResponseData { MsgCode = 1, Message = "系统内部异常!请联系管理员!", Data = exceptionData };
    
                }
    
                actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.BadRequest, responseData, jsonMediaTypeFormatter);
            }
        }

    对于不同级别的过滤器,执行顺序是:

    AuthenticationFilter > ActionFilterAttribute > ExceptionFilterAttribute

    4、IIS WebDAV 模块

    在每次发布后,出现一个问题:跨域和Put请求不了。

    对于这个问题,是已经配置过的怎么还会出现这个问题。

    经过反复的测试,原来是 IIS WebDAV 模块,虽然配置了,IIS 是直接修改 Webconfig 文件的,再次发布覆盖了这个文件原有的配置就没了。

    对于这个问题,可以在 Webconfig 文件里面配置上,这样可以。

    也可以直接去掉 WebDAV 模块,但是卸载不好卸载。可以在 IIS 站点配置文件里面删除 WebDAV 的配置,这样也可以达到效果。

  • 相关阅读:
    spring的工厂类
    spring的基于XML方式的属性注入
    github上传大于100M的文件报错
    fatal: HttpRequestException encountered
    VAR 学习笔记3
    You are my great sunshine
    warning: LF will be replaced by CRLF in
    术语词汇
    XGBoost学习笔记2
    四大基本算法思想
  • 原文地址:https://www.cnblogs.com/zhurong/p/10259447.html
Copyright © 2011-2022 走看看