WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

ASP.NET / IIS の要求サイズの制約

by WebSurfer 20. November 2019 13:55

ASP.NET と IIS には要求のサイズを制限する組み込みのセキュリティ機能があります。httpRuntime 要素の maxRequestLength 属性と requestLimits 要素の maxAllowedContentLength 属性が良く知られています。

それ以外に serverRuntime 要素の uploadReadAheadSize 属性というのもあって、それに気が付かないでハマるということがありましたので、備忘録としてまとめて書いておきます。元の話は Teratail のスレッド「asp.net ajax upload でエラーになる」です。

(1) httpRuntime 要素の maxRequestLength 属性

ASP.NET の制限でデフォルトで 4MB になっています。詳しくは Microsoft のドキュメント httpRuntime 要素 (ASP.NET 設定スキーマ) を見てください。肝心な部分のみ以下に抜粋しておきます。

"入力ストリームのバッファリングしきい値の限界値を KB 単位で指定します。 この限界値は、たとえば大きいファイルをサーバーにポストするユーザーなどにより引き起こされる、サービス拒否攻撃を防止するために使用できます。既定値は 4096 です。 しきい値を超えると、ConfigurationErrorsException 例外がスローされます。"

(2) requestLimits 要素の maxAllowedContentLength 属性

IIS7 から導入された要求のフィルタリング <requestFiltering>の機能の中の requestLimits 要素の maxAllowedContentLength 属性がそれで、デフォルト値が 30,000,000 バイトになっています。下の IIS Manager での設定画面を見てください。

maxAllowedContentLength 属性

設定変更は上の画像のように IIS Manager で行うのがお勧めです。applicationHost.config ファイルをメモ帳などで開いて編集することでも可能ですが。

(3) serverRuntime 要素の uploadReadAheadSize 属性

以下の IIS Manager の画像の通りデフォルトで 49,152 バイトになっており、この制約にかかると HTTP 413 Request Entity Too Large というエラーになります。上に紹介した Teratail のスレッドの話がこの問題です。

uploadReadAheadSize 属性

Microsoft のドキュメント Solution for “Request Entity Too Large” errorLarge file upload failure for Web application calling WCF service – 413 Request entity too large によると、SSL 通信を利用しているとき、または WCF に要求を出す場合は uploadReadAheadSize 属性の制約の影響を受けるとのことです。

ただ、SSL だけでそういう問題が出るとすると FAQ レベルの話&周知の事例なのに、ググって調べた限りそうでもなさそうなのが不思議でした。

さらに調べてみると、IIS randomly returns 413 Request Entity Too Large when uploading large files and using TLS という記事が見つかり、それによると client certificate も絡んだ問題と書いてあります。

上の記事の回答で黄色のバックグラウンドとなっている部分は IIS Express を使った時のエラーメッセージのようです。その中に:

Most likely causes: The Web server cannot service the request because it is trying to negotiate a client certificate but the request entity is too large.

If using client certificates, try: Increasing system.webServer/serverRuntime@uploadReadAheadSize

・・・とあります。

実際、上に紹介した Teratail の記事の問題のサイトでは client certificate を使っているようです。

ただし、自分の環境の Visual Studio Community 2015 で IIS Express で SSL 通信を利用する設定にし、sslFlags を SslNegotiateCert に設定して試してみましたが、uploadReadAheadSize はデフォルトの 49,152 バイトのままでも問題を再現できませんでしたが・・・

(4) JSON 文字列を送信する場合の制約

JSON 文字列のデシリアライズに使用されている(と思われる)JavaScriptSerializer クラスの MaxJsonLength プロパティによって、Web サービスの場合はデフォルトで 102,400 文字に、ASP.NET MVC のアクションメソッドの場合は 2,097,152 文字に制限されています。

前者(Web サービス)の方は jsonSerialization 要素の maxJsonLength 属性の設定によって変更可能です。後者(ASP.NET MVC のアクションメソッド)の場合は 2,097,152 文字から変更できません。

2013 年時点の情報なので今は変更されているかもしれませんが、詳しくは別の記事「MVC は maxJsonLength を無視」を見てください。

Tags: , ,

ASP.NET

Firefox と PostBackUrl

by WebSurfer 9. March 2019 15:51

ASP.NET Web Forms アプリで、クロスページポストバックにより別のページに遷移し、その後ブラウザの戻るボタンで元のページに戻った場合、ブラウザによってはページングなどの機能が働かなくなる(ページングしたいのにクロスページポストバックされてしまう)という話を書きます。元の話は Teratail のスレッド「DataPagerの挙動について」のものです。

form 要素の action 属性

ASP.NET Web Forms アプリでは form 要素の action 属性に自身のページの url が設定されますので、ボタンクリックなどの操作で form が submit されると自身のページに POST されます。それが ASP.NET での既定の動きで「ポストバック」と呼ばれています。

クロスページポストバックとは、自身のページではなく、他のページに POST することです。それには、Button などに用意されている PostBackUrl プロパティにポスト先のページの url を設定します。それにより、Button が html の input 要素に変換された時、その onclick 属性にクロスページポストバックを行うためのクライアントスクリプトが設定されます。

その Button をクリックすると、まず onclick 要素に設定されたクライアントスクリプトが動いて form 要素の action 属性が PostBackUrl プロパティに設定された url に書き換えられ、その後 form が submit されます。結果、クロスページポストバックが行われるという仕組みになっています。(詳しい説明は上に紹介した Teratail のスレッドにありますのでそちらを見れください)

予期せぬ動きと言うのは何かと言うと、ブラウザによっては、クロスページポストバックで別ページに遷移後、戻るボタンをクリックして元のページを表示した場合、PostBackUrl が設定されてないボタンをクリックしてもクロスページポストバックされてしまうことです。

上に紹介した Teratail のスレッドの話はページャーの話でしたが、ページャーに限らす、ポストバックすることにより動くソート、編集などのボタンクリックでも同様にクロスページポストバックされてしまいます。

この記事を書いた時点で自分が試した限りですが、Firefox 65.0.2 と Safari 5.1.7 がそういう動きをするブラウザでした。IE11, Edge 44.17763.1.0, Chrome 72.0.3626.121, Opera 58.0.3135.90 は期待通り自身のページにポストバックされました。

何故ブラウザによってそういう予期せぬ動きになるかと言うと、ページをキャッシュに保存するタイミングの違いです。

ASP.NET Web Forms アプリのデフォルトのキャッシュコントロール設定では、ブラウザは別のページに遷移する前に元のページをキャッシュに保存します。遷移後、ブラウザの戻るボタンをクリックすると、ブラウザは元のページをキャッシュから取得します。そこのところは Firefox に限らず IE でも Chrome でも同じです。

Firefox, Safari はクロスページポストバックを行うためのクライアントスクリプトが動いて form 要素の action 属性が別ページの url に書き換えられた後キャッシュに保存するのに対し、IE, Edge, Chrome, Opera は書き換える前(即ち、action 属性が自身のページの url の時)にキャッシュするという違いがあります。(ブラウザとしてどちらが正解かはいろいろ議論があるところと思いますが、その話はちょっと置いときます)

この記事の上の画像は Firefox でクロスページポストバックで別ページに遷移後、戻るボタンで元のページを表示し、開発ツールで html ソースの form 要素を表示したものです。action 属性の url は別ページに書き換えられています。

この状態では、PostBackUrl の設定有無にかかわらず、form を submit する操作をすれば、action 属性に設定されたページにクロスページポストバックされてしまうという訳です。

先の記事「PostBackUrl と Page.PreviousPage」にも書きましたが、PostBackUrl(クロスページポストバック)はいろいろ問題が多く、どうしても必要というケースもなさそうですので、使わないようにすべきと思っています。

Tags: ,

ASP.NET

ブラウザ画面でセンタリング

by WebSurfer 1. November 2018 12:10

CSS のみを使ってブラウザ画面上でコンテンツを上下左右センタリングする方法を、あまり需要はないとは思いますが、せっかく考えたので備忘録として書いておきます。

センタリング表示

上の画像は、width / height を 500px / 300px に設定した div 要素を、CSS の position プロパティを使って、ブラウザ画面の中央に来るようにしたものです。ブラウザの画面のサイズを変えても自動的に中央に来るようになっています。

CSS の設定は下にアップしたコードにありますので見てください。position を absolute とし、top / left を 50%(即ち画面の中央)に指定、margin に div 要素のサイズの半分をマイナス値で設定することにより div 要素が画面の中央に来るようにオフセットしています。

position プロパティの詳しい説明&デモは MDN web docs の記事「position」にありますので見てください。要点を抜粋すると以下の通りです。

An absolutely positioned element is an element whose computed position value is absolute or fixed. The top, right, bottom, and left properties specify offsets from the edges of the element's containing block. If the element has margins, they are added to the offset.

上の画像を表示したコードを以下にアップしておきます。ASP.NET Web Forms アプリの .aspx ページを使っていますが、ASP.NET は今回の記事には直接の関係はありません。(.html ページを使うとブラウザのキャッシュをいちいち消さなければならないのが面倒なので .aspx ページを使いました)

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="0049-Centering.aspx.cs" 
    Inherits="_0049_Centering" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Centering</title>
    <style type="text/css">
        body {
            background-color: #555;
        }

        .content {
            background-color: white;
            width:500px;
            height:300px;
            position:absolute;
            top:50%;
            left:50%;
            margin-left:-250px;
            margin-top:-150px;
            overflow:scroll;
        }
    </style>
</head>
<body>
  <form id="form1" runat="server">
    <div class="content">
      <h1>
        This page is horizontally / vertically centered on 
        screen that is wider than 500 / 300 pixels.
      </h1>
      <h2>
        Resize the browser window to see the effect.
      </h2>
      <p>
        An absolutely positioned element is an element 
        whose computed position value is absolute or fixed. 
        The top, right, bottom, and left properties specify 
        offsets from the edges of the element's containing 
        block. (The containing block is the ancestor 
        relative to which the element is positioned.) 
        If the element has margins, they are added to the 
        offset.
      </p>
    </div>
  </form>
</body>
</html>

Tags:

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  April 2020  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar