在MVC中执行操作之前解压缩操作筛选器

时间:2018-01-18 18:29:56

标签: asp.net-mvc filter compression

我写了一个动作过滤器,对某些动作的响应进行压缩。

我也想写一个DecompressRequest属性。发件人中有一个请求或2可能相当大,我希望可以选择压缩它们的结尾。有没有办法让OnActionExecuted注入​​一些可以检测它是否被压缩的代码 - >解压缩然后将其提交给正常的MVC路由解析机制?

我只是想知道在哪里放置我的代码以及如何将其注入MVC​​,不需要任何人为我编写解压缩代码。

1 个答案:

答案 0 :(得分:0)

所以这是一个有效的ApiController示例,你可能不得不为普通控制器构造它,因为ApiController要求参数对于帖子有点不同。绝对不可能'正如其他人声称的那样。

using System;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using System.IO.Compression;
using System.Web.Http.Filters;
using Nito.AsyncEx.Synchronous;
using System.Collections.Generic;
using System.Web.Http.Controllers;


namespace MyProject.Models
{
    public class DecompressRequestAttribute : ActionFilterAttribute
    {
        private bool IsRequestCompressed(HttpActionContext message)
        {
            foreach(var encoding in message.Request.Content.Headers.ContentEncoding)
            {
                if(encoding.Equals("gzip",StringComparison.OrdinalIgnoreCase))
                    return true;
            }

            return false;
        }

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if(actionContext.Request.Method.Method == "POST" && actionContext.ActionArguments.Count == 1 && IsRequestCompressed(actionContext))
            {
                Stream stream = actionContext.Request.Content.ReadAsStreamAsync().WaitAndUnwrapException();

                if (stream != null)
                {
                    using (MemoryStream decompressed = new MemoryStream())
                    {
                        using (GZipStream compression = new GZipStream(stream, CompressionMode.Decompress))
                        {
                            int amount;
                            byte[] buffer = new byte[2048];
                            stream.Seek(0, SeekOrigin.Begin); //Stupid stream doesn't start at beginning for some reason
                            while ((amount = compression.Read(buffer, 0, buffer.Length)) > 0)
                                decompressed.Write(buffer, 0, amount);
                        }

                        string json = Encoding.UTF8.GetString(decompressed.ToArray());
                        foreach (HttpParameterDescriptor parameter in actionContext.ActionDescriptor.GetParameters())
                        {
                            actionContext.ActionArguments[parameter.ParameterName] = JsonConvert.DeserializeObject(json, parameter.ParameterType);
                        }                                 
                    }
                }
            }

            base.OnActionExecuting(actionContext);
        }
    }
}