- - PR -
[ASP.NET] ViewStateは無効です。に対するアプローチについて
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-04-11 12:34
いつもお世話になっております。
[ViewStateは無効です。壊れている可能性があります。] のエラーが発生した場合に、ユーザに対する対応方法を考えているのですが、 お知恵を貸してください。 上記のエラーが発生する場合は 1. 本当に不正なデータが送られた (古いブラウザなどが"+"をうまく処理できないケースがありました。 ・または本当に改ざんしている) 2. アプリケーションがリスタートした場合 (DLLを更新・ASP.NETがメモリオーバなどで自動再起動など) 再起動される前にアクセスされたブラウザの情報で、再起動後にPOSTBACKされる。 が考えられます。他の場合もあるかも。。 大半は2.のケースで発生しています。 どのページでも発生し得るので、 Global.asax の OnErrorで HttpExceptionを捕らえてフォローしようと考えています。 1.HttpException例外が発生されるようなのですが、 HttpExceptionの中でも「ViewStateは無効です。」の場合だけ、 対応したい場合判断はどのようにすればよいでしょうか。 ExceptionのMessageで判断するしかないのでしょうか。 (例外のメッセージだけでは、ユーザには理解しがたいので、 補足の説明を加えたいと考えています。) 2.対応方法を次のように考えています。 A.エラーに対する説明を表示する B.表示の中に呼び出されたURLをPOSTでなく、再度GETから読むように Request.Urlの情報へのリンクを加える。 メッセージの説明としては、上記エラー発生原因をもう少し噛み砕いた内容で記述するつもりですが、そもそもエラーの原因として、私の認識に不足はないでしょうか。 またみなさんは、どのようになされていますか? | ||||||||
|
投稿日時: 2003-04-24 22:58
aoppです。
質問の答えになっていないのですが、1点質問があります。 「古いブラウザなどが"+"をうまく処理できないケースがありました。 」 上記は、name="__VIEWSTATE" value="dDwtNTMwNzcx+”に"+"があるときですか!!! あと古いブラウザとは、 逆に質問で申しわけありません。 machine.configの<customErrors>で、エラーステータス(HTTP)を使用し、エラー対応.aspxを振り分けていますが、確かにフォローするには、ExceptionのMessage内の文字列で判断するしかないかも | ||||||||
|
投稿日時: 2003-04-26 07:30
ViewState破壊のエラーは、ご指摘の2)以外でも発生すると思われます。 たとえば、HTMLの__VIEWSTATEが破壊されているときなどが該当します・・・ 私のサイトでは、2)の条件に該当しないのに1日に数回発生しています。 なぜか、TCPが破壊されたHTMLを認識しないで渡すことがあるようです。 この辺をもう少し調査してみたらどうでしょうか・・・・ エラーが発生ときの対処よりも、エラー発生の原因とエラーを発生させないような 対処が必要と思われます。 対処方法: 1) ViewStateに保存する情報を必要最小限にする DataGridなどを使用するときは、EnableViewState="False"を適用する。 2) ViewStateの代わりにSession変数に保存する 個人的には、2)がお勧めです。 この場合、 LoadPageStateFromPersistenceMedium() と SavePageStateToPersistenceMedium() を Overrideすれば可能と思います。 | ||||||||
|
投稿日時: 2003-04-28 16:04
ご回答いただきありがとうございます。
古いというのは、語弊があるかもしれません。 iBoxというセットトップボックスと、i-modeのエミュレータActiveMascotで発生しました。 [1+1] と送信すると、 [1 1]と送られていました。
貴重な情報ありがとうございます。 私のところでも、1日に数件、このエラーが発生しています。 以前は、先にあげたケースだったのですが、最近は、そうとも限らない状況 もありましたので、どうしたらよいか苦慮しておりました。 また、なかなか再現性のある現象でもなく、開発環境ではまず発生しない ケースなものですから。 ViewStateの制御を見直してみたいとおもいます。 Sessionだと便利ですが、かなりデータが大きくならないかちょっと心配。 | ||||||||
|
投稿日時: 2003-05-08 10:52
最近ASP.NETを始めたばかりなので勘違いがあるかもしれませんが、よろしくお願いします。
私の環境ではページを表示した後にIISを再起動し、そしてPostBackしても特にエラーにはなりません。 何か条件でもあるのでしょうか? また、Global.asaxでのエラートラップですが、以下の方法で主要原因の例外を取得しても「ViewStateは無効です。」を判断できないのでしょうか? Server.GetLastError().GetBaseException() | ||||||||
|
投稿日時: 2003-05-09 19:36
私も自身で意図的に操作しても、同様の例外は発生しないのです。 未処理の例外が発生した場合に、メールで例外の内容を 管理者に通知するようにしているのですが 先の事例2のケースの時にアクセスされていたユーザのリクエストで発生します。 (すべてのユーザで発生するのではなく、何らかの条件が重なったときに一部のユーザの リクエストで発生しているのだとおもいます。詳しくは私もわかっていません。)
はい。これで取得できるのは、HttpExceptionが取得できるのですが、 HttpExceptionの発生条件は他にもありますので、中でもViewStateエラーの場合の判別 方法というのがあれば、知りたいところであります。 | ||||||||
|
投稿日時: 2003-05-09 19:44
Mr.ADO.NETさんに紹介いただいた方法を実装してみました。
Sessionに保持するのではなく、サーバのファイルに保存しています。 負荷・ディスクスペースなどはこれから監視しながら、さらに検討していくつもりです。 作成した内容をご紹介まで。 Pageクラスを継承した ViewStateFilePageクラスを作成し、必要な ページでの継承を Pageクラスではなく、ViewStateFilePageクラスを使用しています。 ------------------------------------------------------------------- /// <summary> /// ViewStateの保存先をユーザへのHTMLレスポンスではなく、 /// サーバ上のディスクに保存するページオブジェクト /// </summary> public class ViewStateFilePage : System.Web.UI.Page { public ViewStateFilePage() :base() { } /// <summary> /// ViewState値の保存先のファイル名を取得します。 /// Web.Config で設定された VIEWSTATE_PATH キーの値 / AppDomainのHash値/ SessionID値 / パス名(パスの[/]は[_]に置き換えられます) /// のファイル名を取得します。 /// /// </summary> /// <returns></returns> protected string GetViewStateFileName() { string dir = Server.MapPath(string.Format("{0}{1}",System.Configuration.ConfigurationSettings.AppSettings["VIEWSTATE_PATH"],AppDomain.CurrentDomain.GetHashCode())); if(!Directory.Exists(dir)) Directory.CreateDirectory(dir); dir = dir + "\\" + Session.SessionID; if(!Directory.Exists(dir)) Directory.CreateDirectory(dir); return string.Format("{0}\\{1}.txt",dir,Request.CurrentExecutionFilePath.Replace("/","_")); } /// <summary> /// ViewStateの読込先をディスクから読み込むようにオーバライドします。 /// ファイルの読取に失敗した場合は、null値を返します。 /// </summary> /// <returns></returns> protected override object LoadPageStateFromPersistenceMedium() { string path = GetViewStateFileName(); System.Web.UI.LosFormatter los = new LosFormatter(); try { using(Stream s = new FileStream(path,FileMode.Open)) { return los.Deserialize(s); } } catch(System.IO.IOException) { return null; } } /// <summary> /// ViewStateの保存先をファイルに書き込むようにオーバライドします。 /// ファイルの書き込みに失敗した場合は、ViewStateの値は失われます。 /// </summary> /// <param name="viewState"></param> protected override void SavePageStateToPersistenceMedium(object viewState) { LosFormatter los = new LosFormatter(); string path = GetViewStateFileName(); try { using(Stream s = new FileStream(path,FileMode.Create,FileAccess.Write)) { los.Serialize(s,viewState); } } catch(System.IO.IOException) { } } } | ||||||||
|
投稿日時: 2003-05-12 04:41
ブラウザの「戻る」ボタンを有効にする場合、このサンプルの仕様ですと
常に最新のViewStateが復元されると思うのです・・・ __VIEWSTATEにIDを埋め込んでおいて、ID別にViewStateを保存する方法も あります。 たとえば、「戻る」ボタンを5回まで許可するときは、5世代分の IDを管理します。ViewStateを復元するときは、__VIEWSTATEに格納されている IDを基に復元します。 |