IIS 7:JSON応答の圧縮

数日前、私の友人は、彼の大きなJSON応答(0.5〜1メガバイトのオーダー)がパックされていないことに気付きました。 Windows 2008 R2 + IIS 7.5 + ASP.NET MVC 4の作業束。問題が特定され、ソリューションの検索が開始されました。 アクションを再現するために、この記事用に別のアプリケーションを作成しました。



対処方法



public ActionResult Index() { if (Request.IsAjaxRequest()) { return Json(new {/*  */}, JsonRequestBehavior.AllowGet); } return View(); }
      
      





提出



 <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"></script> <script type="text/javascript"> jQuery(function ($) { $.ajax({ url: '@Url.Action("Index")' }); }) </script>
      
      





最初にチェックされたのはHTTPヘッダーです。







スクリーンショットは、ajaxリクエストがX-Requested-With: XMLHttpRequest



あり、ブラウザーがgzipを理解するか、 Accept-Encoding: gzip, deflate



ヘッダーでAccept-Encoding: gzip, deflate



し、サーバーがjson Content-Type: application/json



で応答することを報告していますが、 Content-Encoding



ヘッダーがないため、圧縮されません。



次に、インストールされたWebサーバーモジュールのチェックを行いました管理ツール->サーバーマネージャー->ロール-> IIS







静的/動的コンテンツ比較がインストールされています。 (Windows 7のインストールはコンポーネントの追加/削除によって実行されるため、注意が必要です)。

次に、IIS上のアプリケーションで圧縮が有効になっているかどうかを確認します。











そうでない場合は、変更を確認して適用します。 圧縮はweb.config



でも可能web.config







 <system.webServer> <urlCompression doStaticCompression="true" doDynamicCompression="true" /> </system.webServer>
      
      





構成エディター-> system.webServer-> urlCompression















IISはすべて正常に処理されているように見えますが、IISは応答ヘッダーでContent-Encoding



を提供しなかったため、まだそうではありません。



行ってきました



 <system.webServer> <httpCompression> <dynamicTypes> <add mimeType="application/json" enabled="true" /> <add mimeType="application/json; charset=utf-8" enabled="true" /> </dynamicTypes> </httpCompression> </system.webServer>
      
      





そして、歓声、勝利、待望のContent-Encoding: gzip



を取得します。 しかし、非常に大きなものが1つあります。 httpCompression



セクションはapplicationhost.config



のみ定義できapplicationhost.config



。 これは、あなたがIIS管理者であるか、このオプションがあなたに合わないことを意味します(もちろん、あなたが反対をホストに納得させない限り)。



見つかったオプションがあなたに合わないが、答えを圧縮する必要があると仮定します。 動的圧縮の設定にデフォルトであるもの。







圧縮は、たとえばtext/javascript



適用されtext/javascript



。 もちろん、これはハックのように見えますが、何もないよりはましです。



アクションメソッドを



 public ActionResult Index() { if (Request.IsAjaxRequest()) { return new JsonResult() { ContentType = "text/javascript", ContentEncoding = Encoding.UTF8, JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = new {/*  */} }; } return View(); }
      
      





また、 $.ajax



関数を使用して応答すると、すぐにデータ解析エラーが発生します。 つまり、ここで$.getJSON



使用するか、 json



を期待していることを明示的に示す必要があります。



提出



 <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"></script> <script type="text/javascript"> jQuery(function ($) { $.ajax({ url: '@Url.Action("Index")', dataType: 'json', }); }) </script>
      
      





そして、現れたがそれらのタスクに適合しなかった3番目の解決策(これは注意を払う価値がないという意味ではありません)は、自分でパックすることです。



私は完全に同意するスタックから例を挙げます



 public class CompressAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"]; if (string.IsNullOrEmpty(encodingsAccepted)) return; encodingsAccepted = encodingsAccepted.ToLowerInvariant(); var response = filterContext.HttpContext.Response; if (encodingsAccepted.Contains("deflate")) { response.AppendHeader("Content-encoding", "deflate"); response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); } else if (encodingsAccepted.Contains("gzip")) { response.AppendHeader("Content-encoding", "gzip"); response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); } } }
      
      





データ圧縮率



上記で遊んでいると、もう1つの興味深いことに気づきました。Fiddlerの圧縮されたコンテンツがアンパックされ、フィード自体によって再パックされました。 IISの圧縮設定を見つける方法、想像できません。 3番目のオプションとは別に、 CompressionLevel



コンストラクターパラメーターを使用できます。 たぶんあなたの一人が教えてくれますか? プロジェクトによっては、送信されるトラフィックの量が重要になる場合があり、それどころか、プロセッサ時間がかかるため、この点は自分にとって重要だと考えています。



一見、どんなにクレイジーなアイデアであろうと、問題を解決するための選択肢が増えて嬉しいです。



All Articles