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



我编写了一个操作过滤器,用于压缩某些操作的响应。

我也想写一个解压缩请求属性。发件人有一两个请求可能相当大,我想选择性地压缩它们。有没有办法像 OnActionExecute 一样注入一些代码来检测它是否被压缩 ->解压缩它,然后将其提交给正常的 MVC 路由解析机制?

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

所以这是一个有效的 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);
        }
    }
}

最新更新