Wednesday, March 28, 2012

ViewState and Atlas

Hi

I encountered a problem involving viewstate and PageMethods (web methods in an aspx page).

I was submitting some control values, only one control on the page is designed as a <asp:listbox />, the rest of the controls are generic HTML. While Atlas.js constructed the proxy to the PageMethod and the arguments (Web.Net.PageMethodRequest) the Atlas.js javascript does some sort of check on the page controls, in which viewstate is a hidden input, adding it to a dictionary (refer line 3495 in Atlas.js)

Some sort of exception is generated but no information is available to determine the source. The code behind to the PageMethod didn't get hit in debug mode and it wasn't until I inspected the request/response in Fiddler that I came across a message indicating a corrupted viewstate.

After disabling viewstate on the <asp:listbox> the request got through to my [WebMethod] in the code-behind.

There is a problem with PageMethods and viewstate, or have I missed something.

Craig

An update for those who might be encountering the same problem with altas (Jan-06 CTP) and ViewState.

As mentioned in my previous post, in the file Atlas.js on line 3495, a procedure adds to the variable bodyDictionary all 'submittable' HTML element e.g <input /> this includes <input type="hidden" /> which means that<inputid="__VIEWSTATE" /> is added to the bodyDictionary variable.

Next in the procedure, is a call Web.Net.WebRequest.createQueryString(bodyDictionary, ...);

This is where IMHO the viewstate corruption is occuring between the client service calls to the server. In my case, I make a call to a [WebMethod] which is contained in an aspx page. So my client function is something like this:

functionfoo() {
PageMethod.GetFoo('hello');
}

My aspx.cs [WebMethod] is like the following:

[WebMethod]
public string GetFoo(string text) {
return text+=" get foo";
}

My page wrapes a user control in an<atlas:UpdatePanel>the user control contains an<asp:Repeater>control.

Has anyone experienced this, or am I the lucky one? To avoid the error 500, I removed the check for HTML elements with a type of hidden. But I'm not sure if this is a good thing...

Craig

PS: I can post the stack trace for those who might be interested.


Further, using PageMethod seems to faciliate the viewstate corruption. for kicks I moved the [WebMethod] from the aspx page into an ASMX file, reversed my Atlas.js script hack and the viewstate problem has gone. I hope the PageManager is a little more robust in the rtm.


Hi,

I'm not able to reproduce the behavior that you described. Could you post the stack trace and also the relevant page code?

Hi Garbin

Stack Trace
[FormatException: Invalid length for a Base-64 char array.]
System.Convert.FromBase64String(String s) +0
System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) +72
System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState) +4
System.Web.UI.ClientScriptManager.EnsureEventValidationFieldLoaded() +172

[ViewStateException: Invalid viewstate.
Client IP: 127.0.0.1
Port: 3520
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
ViewState: /wEWCAKbhpuAAgLEtM6pBgLN/7aVCAKe4MuSDQLL7+H/CgLL7 3/CgKs5ZucDgLNoqBMLo1Lj5/N S5y dQM87L I5JMzQ=
Referer:http://localhost/Unsd/COC/ExchangeRateView.aspx?countryCode=36
Path: /Unsd/COC/ExchangeRateView.aspx]

[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) +116
System.Web.UI.ClientScriptManager.EnsureEventValidationFieldLoaded() +209
System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument) +67
System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument) +106
System.Web.UI.WebControls.TextBox.LoadPostData(String postDataKey, NameValueCollection postCollection) +31
System.Web.UI.WebControls.TextBox.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection) +11
System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +408
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +6953
System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +154
System.Web.UI.Page.ProcessRequest() +86
System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +18
System.Web.UI.Page.ProcessRequest(HttpContext context) +49
ASP.exchangerateview_aspx.ProcessRequest(HttpContext context) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\unsd_coc\bdef81f1\ee1d3cb5\App_Web_ytigk7vl.8.cs:0
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +154
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64

Page Code (aspx.cs)
[WebMethod]
publicExchangeRate GetExchangeRate(int countryCode,int year) {
returnCountryManager.Instance.GetExchangeRate(countryCode,
newint[] { year });
}

Page Code (aspx - javascript)
function GetExchangeRate(countryCode, year) {
// Call the server.
PageMethods.GetExchangeRate(countryCode, year, RequestCallback);
}

function RequestCallback(exchangeRate) {
// Bind the result to the controls.
document.getElementById("ctl00_contentPlaceholder_textboxYear").value = exchangeRate.Year;
document.getElementById("ctl00_contentPlaceholder_textboxIMF").value = exchangeRate.IMF;
document.getElementById("ctl00_contentPlaceholder_textboxUNOP").value = exchangeRate.UNOP;
document.getElementById("ctl00_contentPlaceholder_textboxOther1").value = exchangeRate.Other1;
document.getElementById("ctl00_contentPlaceholder_textboxOther2").value = exchangeRate.Other2;
document.getElementById("ctl00_contentPlaceholder_textboxNote").value = exchangeRate.Note;
}

Page Code (aspx - html)
<!-- Exchange Rate Control -->
<atlas:UpdatePanelID="updatePanelExRate"runat="server"Mode="Conditional">
<ContentTemplate>
<unsd:ExchangeRateControlid="exchangeRateControl"runat="server"/>
</ContentTemplate>
<Triggers>
<atlas:ControlEventTriggerControlID="buttonSave"EventName="Click"/>
</Triggers>
</atlas:UpdatePanel>

The ExchangeRate control is populated in the Page_Load event of the aspx Page by passing an array to a property accessor in the control, the array provides is the data source to a repeater. The ItemTemplate in the repeater contains a link to invoke the GetExchangeRate javascript in the page (above).

Hope this helps.

Craig


I don't know if its the same issue or not, but viewstate corruption is rampant in the QuickStart tutorials... There were several times where I ran 3 or 4 different "run this" tutorials in a row only to have the viewstate corruption error message appear on me. Sometimes it was fixed with a refresh of the page, sometimes it never went away.
hi Guys...
even i got the same problem when i put my [webmethod] in code behind.i tried removing type=hidden from atlas.js line 3495 and it is working.please let me know for the solution as we just can not remove any thing from coreatlas files even though doing the same results in expected output.

thanks
Jaideep

I tried a few things, but was not able to repro. Could you give this a try with the March CTP to see if it still happens?

thanks,
David


I have a similar problem with teh session state.

I have narrowed it down to a web user control that raises an event.

The code behind that implements the event sets the session var and then does a redirects.

on the redirect page the session state is blown away. cant figure out why

steps to reproduce

- create a web user control (define an event and raise it)

- create a page and place the wuc on it (trap for the wuc event and set a session var and do a redirect to 2nd page

- in 2nd page Page_load check the session state

No comments:

Post a Comment