基本的に、ポストバック間でオブジェクトを永続化するために ViewState を使用しようとしています。さらに、これらのオブジェクトをプライベート クラスのプロパティ内にカプセル化しようとしています。
これの目的は、以前は静的フィールドを使用してオブジェクトを永続化していた既存のコードをリファクタリングすることであり、これは明らかに問題を引き起こしていました。
以下は、Web フォームの HTML の非常に単純な例です。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication3.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
</div>
</form>
</body>
</html>
そして、これは最初のコード ビハインドの非常に単純な例です (私が書いたものではありません)。
using System;
using System.Web.UI;
namespace WebApplication3
{
public partial class WebForm1 : Page
{
private static string[,] _my2DArray;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
_my2DArray = new string[3,3];
for (var i = 0; i < 3; i++)
{
for (var j = 0; j < 3; j++)
{
_my2DArray[i, j] = Guid.NewGuid().ToString();
}
}
}
TextBox1.Text = _my2DArray[1, 1];
}
}
}
これにより、ポストバック間でオブジェクトを永続化するという目標が達成されますが、他のすべての間でもオブジェクトが永続化されるため、問題が発生します。
私のアイデアは、このオブジェクトを使用する多くの分離コードがあり、実際のアプリケーションにはさらに多くのオブジェクトがあるため、このようなものにリファクタリングすることでした。できるだけコードを変更せずに問題を修正したいと考えています (resharper を使用すると、フィールドを別のクラスに移動して、それらをプロパティに変換することが簡単になります。次に、プロパティ コードを修正して、プライベート バッキングではなく Viewstate と連携するようにしました。分野):
using System;
using System.Web.UI;
namespace WebApplication3
{
public partial class WebForm1 : Page
{
internal class MyClass
{
private readonly WebForm1 _webForm1;
internal MyClass(WebForm1 webForm1)
{
_webForm1 = webForm1;
}
internal string[,] My2DArray
{
set { _webForm1.ViewState["_my2DArray"] = value; }
get { return (string[,])_webForm1.ViewState["_my2DArray"]; }
}
}
private MyClass _myClass;
protected void Page_Load(object sender, EventArgs e)
{
_myClass = new MyClass(this);
if (!IsPostBack)
{
_myClass.My2DArray = new string[3,3];
for (var i = 0; i < 3; i++)
{
for (var j = 0; j < 3; j++)
{
_myClass.My2DArray[i, j] = Guid.NewGuid().ToString();
}
}
}
TextBox1.Text = _myClass.My2DArray[1, 1];
}
}
}
これはほとんど機能しました。2D 配列だけでなく、このメソッドを使用して期待どおりに機能する文字列の int と boolean があります。しかし、2 次元配列を混在させると、次のエラーが発生します。
このページの状態情報は無効であり、破損している可能性があります。
ソース エラー:
[該当するソース行はありません]
スタックトレース:
[EndOfStreamException: Unable to read beyond the end of the stream.]
System.IO.BinaryReader.ReadByte() +9616466
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +44
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +380
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +141
[ArgumentException: The serialized data is invalid.]
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +205
System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) +337
System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState) +4
System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState) +37
System.Web.UI.HiddenFieldPageStatePersister.Load() +147
[ViewStateException: Invalid viewstate.
Client IP: 127.0.0.1
Port:
Referer: http://localhost:27314/WebForm1.aspx
Path: /WebForm1.aspx
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36
ViewState: /wEPDwULLTE0MDM4MzYxMjMPFgIeBkZvb2JhcmRkem7xFcvXyGXVXNDDKHSutQ9j/EhfbWTpihkzXIlH66A=]
[HttpException (0x80004005): The state information is invalid for this page and might be corrupted.]
System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError) +198
System.Web.UI.ViewStateException.ThrowViewStateError(Exception inner, String persistedState) +14
System.Web.UI.HiddenFieldPageStatePersister.Load() +251
System.Web.UI.Page.LoadPageStateFromPersistenceMedium() +106
System.Web.UI.Page.LoadAllState() +43
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +8431
System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +253
System.Web.UI.Page.ProcessRequest() +78
System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +21
System.Web.UI.Page.ProcessRequest(HttpContext context) +49
ASP.webform1_aspx.ProcessRequest(HttpContext context) in c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\37286ff3\6dc3cf92\App_Web_t5caigbu.0.cs:0
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +100
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
私は困惑しています。VS で新しい Webforms ソリューションを作成し、上記の HTML + コード ビハインドをそれぞれのファイルにコピーすると、私が持っているものとまったく同じになります。
Visual Studio 2010 を使用し、.Net 4 をターゲットにしています。
このメソッドを使用してポストバック間で 2D 配列のオブジェクトを永続化するときにこのエラーが発生する理由についてのアイデアはありますが、他のタイプのオブジェクトはありませんか?
乾杯