• Asp.net WebAPi gzip压缩和json格式化


    现在webapi越来越流行了,很多时候它都用来做接口返回json格式的数据,webapi原本是根据客户端的类型动态序列化为json和xml的,但实际很多时候我们都是序列化为json的,所以webapi的序列化比我们用ServiceStack.Text序列化要多花费一些时间,还有如果返回的数据量比较大那么我们应该启动gzip和deflate压缩。而这些实现都不得影响现有的code, 我个人喜欢同时也是习惯用特性来完成压缩和json格式化。

    1.压缩的code:

    namespace MvcApp
    {
        using System;
        using System.Collections.Generic;
        using System.IO;
        using System.Linq;
        using System.Web;
        using System.Web.Http.Filters;
        using System.IO.Compression;
        using System.Net.Http;
        public class CompressAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
            {
                var content = actionExecutedContext.Response.Content;
                var acceptEncoding = actionExecutedContext.Request.Headers.AcceptEncoding.Where(x => x.Value == "gzip" || x.Value == "deflate").ToList();
                if (acceptEncoding != null && acceptEncoding.Count > 0 && content != null && actionExecutedContext.Request.Method != HttpMethod.Options)
                {
                    var bytes = content.ReadAsByteArrayAsync().Result;
                    if (acceptEncoding.FirstOrDefault().Value == "gzip")
                    {
                        actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.GzipCompress(bytes));
                        actionExecutedContext.Response.Content.Headers.Add("Content-Encoding", "gzip");
                    }
                    else if (acceptEncoding.FirstOrDefault().Value == "deflate")
                    {
                        actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.DeflateCompress(bytes));
                        actionExecutedContext.Response.Content.Headers.Add("Content-encoding", "deflate");
                    }
                }
                base.OnActionExecuted(actionExecutedContext);
            }
    
        }
        class CompressionHelper
        {
    
            public static byte[] DeflateCompress(byte[] data)
            {
                if (data == null || data.Length < 1)
                    return data;
                try
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        using (DeflateStream gZipStream = new DeflateStream(stream, CompressionMode.Compress))
                        {
                            gZipStream.Write(data, 0, data.Length);
                            gZipStream.Close();
                        }
                        return stream.ToArray();
                    }
                }
                catch (Exception)
                {
                    return data;
                }
            }
    
            public static byte[] GzipCompress(byte[] data)
            {
                if (data == null || data.Length < 1)
                    return data;
                try
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        using (GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress))
                        {
                            gZipStream.Write(data, 0, data.Length);
                            gZipStream.Close();
                        }
                        return stream.ToArray();
                    }
                }
                catch (Exception)
                {
                    return data;
                }
    
            }
        }
    }

    首先判断客户端是否启动gzip,deflate压缩,如果启用并且请求类型不是Options同时又返回数据,那么我们就压缩返回数据。至于用gzip还是deflate那就看客户端接受的一个压缩是gzip,deflate?

    2.json

    如下:

    public IEnumerable<Users> Get()
    {
    return _userList;
    }

    很多时候我们会把这个api的返回类型改为HttpResponseMessage同时序列化为json格式的数据,写成一个通用的方法大家来调用。我推荐的实现方式采用Attribute来做。

    相关code:

    namespace MvcApp
    {
        using ServiceStack.Text;
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Net;
        using System.Net.Http;
        using System.Reflection;
        using System.Text;
        using System.Web;
        using System.Web.Http.Controllers;
        using System.Web.Http.Filters;
        public class JsonResultConverterAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
            {
                //actionContext.ActionDescriptor.ResultConverter ;
                var actionDescriptor = actionContext.ActionDescriptor;
                var field = typeof(HttpActionDescriptor).GetField("_converter", BindingFlags.NonPublic | BindingFlags.Instance);
              if (field != null)
              {
                  field.SetValue(actionDescriptor, new JsonResultConverter());
                  //actionDescriptor.ReturnType = typeof(HttpResponseMessage);
              }
              var test = actionDescriptor.ResultConverter;
                base.OnActionExecuting(actionContext);
            }
        }
        public class JsonResultConverter : IActionResultConverter
        {
            public HttpResponseMessage Convert(HttpControllerContext controllerContext, object actionResult)
            {
                if (controllerContext == null)
                {
                    throw  new ArgumentNullException("controllerContext");
                }
    
                HttpResponseMessage resultAsResponse = actionResult as HttpResponseMessage;
                if (resultAsResponse != null)
                {
                   // resultAsResponse.EnsureResponseHasRequest(controllerContext.Request);
                    return resultAsResponse;
                }
    
    
                string jsonResult = TypeSerializer.SerializeToString(actionResult);
               var content = new StringContent(jsonResult, Encoding.UTF8, "application/json");
    
               return controllerContext.Request.CreateResponse(HttpStatusCode.OK, jsonResult);
            }
        }
    }

    注意HttpActionDescriptor的私有字段_converter在ResultConverter属性中暴露出来,遗憾的是是个只读属性,所以我们需要用反射来设置它的value(实现IActionResultConverter接口)。

    运行结果我也就不贴图了,代码下载地址:http://download.csdn.net/detail/dz45693/9486586

  • 相关阅读:
    OCP-1Z0-053-V12.02-622题
    OCP-1Z0-053-V12.02-501题
    Flex实现查询和重置
    闪回事务处理回退
    闪回数据归档测试
    闪回数据归档
    OCP-1Z0-053-V12.02-166题
    VC-摄像头控制SDK源码
    MFC 的 Picture Control 加载 BMP/PNG 图片的方法
    OCP-1Z0-051-V9.02-25题
  • 原文地址:https://www.cnblogs.com/majiang/p/5374411.html
Copyright © 2020-2023  润新知