無効なビューステートの問題のトラブルシューティング
このトラブルシューティング ツールで使用されるツール:
- NA
この資料は情報提供のみを目的として提供されています。 Microsoft は、明示的、黙示的を問わず一切の保証をしません。
概要
ビューステートは、サーバーの状態 (セッション状態など) に依存することなく、ページが自動的に状態を保持できるようにする、ASP.NET の機能です。 ただし、ビューステートに関連する問題はデバッグが困難な場合があります。 ほとんどの場合、ビューステートに関する問題が発生すると、Web ブラウザーで次のエラー メッセージが表示され、問題の原因をほとんど示しません。
"The viewstate is invalid for this page and might be corrupted"
この記事では、デバッグやビューステートに関する問題の解決に使用できるいくつかの手法について説明します。
シナリオとトラブルシューティング
修正された問題が発生していないかどうかを確認する
ASP.NET 1.0 修正プログラムとサービス パックでは、ビュー ステートの問題が多数修正されました。これらの修正も ASP.NET 1.1 の一部です。 既に解決されている問題を追跡する前に、最新の修正プログラムを適用していることを確認してください。 Microsoft .NET Frameworkの最新の更新プログラムは、次の Microsoft Developer Network (MSDN) Web サイトから入手できます。
https://msdn.microsoft.com/netframework/aa569276.aspx
Web ファームで実行している場合は、validationKey 属性を設定します
Web ファームでは、各クライアント要求をポストバックごとに異なるコンピューターに送信できます。 この動作のため、Machine.config ファイルで validationKey 属性を AutoGenerate に設定したままにすることはできません。 代わりに、validationKey 属性の値を、Web ファーム上のすべてのマシンで共有される固定文字列に設定する必要があります。
この問題の詳細については、次の記事番号をクリックして、Microsoft サポート技術情報の記事を参照してください。
https://support.microsoft.com/kb/323744
動的に生成された型を Web ファームのビューステートに格納しない
ASP.NET がファイルを動的にコンパイルすると、ファイルは基本的にランダムな名前を持つアセンブリに組み込まれます (たとえば、ファイル名がjp395dun.dllされる場合があります)。 Web ファームを実行している場合、同じファイルが異なるランダムな名前のアセンブリにコンパイルされます。 通常、これは問題ではありません。これは、アセンブリ名に関する前提を誰も行わないためです。 ただし、バイナリシリアル化を使用して動的にコンパイルされた型をビュー ステートに配置した場合、アセンブリの名前はビュー ステート データの一部として含まれます。 そのビューステートが後で Web ファーム内の別のサーバーに送信された場合、ビューステートは異なるアセンブリ名を使用するため逆シリアル化できません。
この問題の最善の解決策は、バイナリシリアル化を使用しないようにすることです。 バイナリシリアル化では、この問題が発生しない場合でも、多くのリソースが使用されます。 代わりに、ビューステートに置くものを、配列、ペア、トリプレット、および単純型 (文字列、int、その他の型など) の組み合わせに制限します。 System.Web.UI.Pair と System.Web.UI.Triplet は、ビュー ステート エンジンが効率的に処理できる単純なラッパー型です。
この問題を回避する別の修正プログラムは、ビュー ステートに格納している型を、Bin フォルダーまたはグローバル アセンブリ キャッシュ内のプリコンパイル済みアセンブリに移動することです。 この修正プログラムはパフォーマンスに対応しませんが、アセンブリがすべてのコンピューターで同じ名前を持っていることを保証します。
注: ビューステートに複雑なデータ型を格納し、この問題が発生した場合、呼び出し履歴情報には次のようなスタックが含まれます。
[FileNotFoundException: Could not load file or assembly 'App_Web_fx--sar9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.]
System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName) +0
System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +72
System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +58
System.Type.GetType(String typeName, Boolean throwOnError) +57
System.Web.UI.ObjectStateFormatter.DeserializeType(SerializerBinaryReader reader) +192
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +943
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +384
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +210
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +142
問題がビュー ステート MAC 機能に関連しているかどうかを判断する
ビュー ステート マシン認証コード (MAC) 機能の目的は、クライアントが悪意のあるビュー ステートを含む要求を送信できないことです。 既定では、この機能は、Machine.config ファイルの次のフラグで有効になっています。
enableViewStateMac="true"
対処している問題が MAC 機能に関連しているかどうかを判断する最も簡単な方法は、機能をオフにすることです。 これを行うには、Machine.config ファイルのフラグを次のコードに変更します。
enableViewStateMac="false"
ビュー ステート エラーが発生しなくなった場合、問題は MAC 機能に関連しています。
重要
問題の診断に役立つビュー ステート MAC 機能のみをオフにします。 問題を回避するには、ビュー ステート MAC をオフのままにしないでください。 その場合は、セキュリティ ホールを導入できます
一般に、出力を HTML エンコードしないすべてのコントロール (DataGrid コントロール、DataList コントロール、ラベル コントロール、その他のコントロールなど) に対してビュー ステートを無効にしているか、または各要求の値を常に安全であることがわかっているものに明示的に設定していることを完全に確信している場合を除き、ビューステート MAC 機能をオフにしないことをお勧めします。
エラー メッセージを受け取ったときに発生する例外を正確に判断する
残念ながら、この記事の「概要」セクションに記載されている無効なビューステートエラーメッセージはあまり有益ではありません。 通常、エラー メッセージは、ビューステートの処理中に例外がスローされたことが原因で発生します。 問題は、例外が使用され、その詳細がエラー メッセージで失われることです。
デバッガーを使用すると、元の例外を特定できます。 これを行うには、デバッガーを ASP.NET プロセス (Aspnet_wp.exeまたはW3wp.exe) にアタッチし、すべての例外をキャッチするように設定する必要があります。 マネージド例外をキャプチャするようにデバッグ診断 1.2 ツールを構成することもできます。
セッションにビューステートを格納してみてください
既定では、表示状態は、ブラウザーに送信される INPUT type=hidden> フィールドによって<ラウンドトリップされます。 その後、ブラウザーは、次の要求でフィールドをサーバーに送り返します。 場合によっては、このビューステートが非常に大きくなり、問題の原因になる可能性があります。 一部のブラウザーでは、このような大きな非表示フィールド (および結果の大きな要求) を処理できず、ブラウザーによってビューステートが切り捨てられる場合があります。 ビュー ステートを切り捨てると、"ビュー ステートが破損しました" というエラー メッセージが表示されます。 この動作は、より単純なブラウザーで発生する可能性が最も高いです。 たとえば、この動作は PDA 上のブラウザーで発生する可能性があります。
このような問題が発生している可能性があるかどうかを判断するには、セッションにビューステートを格納してみてください。 この方法を次の例に示します。
<%@ language=c# debug=true %>
<script runat=server>
protected override object LoadPageStateFromPersistenceMedium()
{
return Session["_ViewState"];
}
protected override void SavePageStateToPersistenceMedium(object viewState)
{
Session["_ViewState"] = viewState;
}
void TextChanged(object o, EventArgs e)
{
Response.Write("TextChanged");
}
</script>
<form runat=server>
<asp:button text=Test runat=server/>
<asp:textbox ontextchanged=TextChanged runat=server/>
<input type=hidden name=__VIEWSTATE>
</form>
次のコード行は、バグを回避するために、ASP.NET 1.0 でのみ必要です。 ASP.NET 1.1 plus では必要ありません。
<input type=hidden name=__VIEWSTATE>
問題がワーカー プロセスのリサイクルによって引き起こされているかどうかを判断する
次のシナリオについて考えてみます。
- Microsoft インターネット インフォメーション サービス (IIS) 6.0 で ASP.NET を実行しています。
- アプリケーション プールは、ローカル システム アカウント、ネットワーク サービス アカウント、または管理レベルのアカウント以外の ID で実行されています。
- MACHINEKEY 要素の <validationKey> 属性は、構成ファイルで AutoGenerate に設定されます。
このシナリオでは、次の手順を実行すると、ビュー ステート エラーが発生します。
- ユーザーがページを参照します。
- ASP.NET アプリケーションをホストするワーカー プロセスがリサイクルされます。
- ユーザーがページをポストバックします。
このシナリオの回避策は、構成ファイルで明示的な validationKey 属性を使用することです。
その他の参照情報
- ASP.NET での "状態の表示が無効です" エラーのトラブルシューティング
- セキュリティで保護された ASP.NET アプリケーションの構築: 認証、認可、セキュリティで保護された通信
- フォーム認証で使用する Visual C# .NET を使用してキーを作成する方法 (
https://support.microsoft.com/kb/312906
)