Showing posts with label client-side. Show all posts
Showing posts with label client-side. Show all posts

Monday, March 26, 2012

Conflict between UpdatePanel and Client-side Callback?

I posted this issue in the ASP.Net Ajax UI forum originally but never got a definitive answer:http://forums.asp.net/t/1184085.aspx

Basically, I have a Timer control outside an UpdatePanel that Ticks every second and triggers the UpdatePanel to display the current date & time. I also have an HTML button that initiates a client-side callback, which simply counts the number of client-side callbacks executed so far, and displays the count on the page. And finally I have a TextBox control placed outside the UpdatePanel. The TextBox isn't used for anything, but it needs to be there for the error to be generated.

The problem is that when I repeatedly click the HTML button to initiate client-side callbacks while the Timer is ticking, I will eventually get the "The state informationis invalidfor this page and might be corrupted"error. To get the error to be thrown I usually have to vary thefrequency of my clicking, but I can reproduce it without too muchtrouble (i.e. between 2 and 30 clicks). I am able to reproduce theerror in both IE and Firefox, though it is much easier to get Firefox to throw the error (to get IE to throw the error, I had to add more server controls to the page).

A poster on the other thread said it sounded like there was a conflict between the UpdatePanel and Client-side callbacks, but couldn't provide any further information. Is this a known issue/limitation? Anyone know what's going on here?

Thecode is below.

<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!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 id="Head1" runat="server">
<title>Testing</title>
<script type="text/javascript">
function initiateCallBack(){
doCallBack(document.getElementById("spanCallBackCount").innerHTML);
}

function callBackComplete(result){
document.getElementById("spanCallBackCount").innerHTML = result;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager
<br /><br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional">
<ContentTemplate>
Date & Time: <asp:Literal ID="ltrDateTime" runat="server"></asp:Literal>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
</asp:UpdatePanel>
<asp:Timer ID="Timer1" runat="server" Interval="1000" OnTick="Timer1_Tick"></asp:Timer
<br /><br />
<asp:TextBox ID="txtTest" runat="server" Text="Testing"></asp:TextBox
<br /><br />
Call Back Count: <span id="spanCallBackCount">0</span>
<br /><br /
<input type="button" id="btnCallBack" name="btnCallBack" onclick="initiateCallBack();" value="Initiate Client-side Callback" /
</form>
</body>
</html

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partialclass _Default : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
{
int callBackCount = 0;

protected void Page_Load(object sender, EventArgs e)
{
string callBackReference = Page.ClientScript.GetCallbackEventReference(this,"cnt","callBackComplete","context");
string callBackScript ="function doCallBack(cnt, context){" + callBackReference +"}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),"doCallBack", callBackScript,true);
}

public void RaiseCallbackEvent(string cnt)
{
callBackCount = Convert.ToInt32(cnt);
callBackCount++;
}

public string GetCallbackResult()
{
return callBackCount.ToString();
}

 protected void Timer1_Tick(object sender, EventArgs e)
{
ltrDateTime.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt");

UpdatePanel1.Update();
}

}

No one can help with this? Come on, one of you Microsoft gurus must be able to provide some input...


Hi,

I tried it but can't reproduce the issue.

It's caused by viewstate validation failure, you can disable it.

<%@. Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" EnableViewStateMac="false"%>


Thanks for the help. Did you test it with Firefox? It's much more difficult to get IE to throw the error. I do get the error with IE, but it's much less consistent (and usually requires me to add more controls to the page). Firefox throws it pretty easily though. I actually created a video of the behavior I'm seeing with Firefox which can be seen here:

http://www.youtube.com/watch?v=EBsMRxnOtpE

(There's no audio, but I'm just running the code that I posted above, so it's not a big deal. In it, I run it with Firefox, and get it to throw the error after 20 clicks).

Unfortunately I can't disable the ViewState as in my real scenario the UpdatePanel and timer are at the top of the page checking every 60 seconds to see if the user has any new messages (internal messages to our system), and a client-side callback is used to maintain the state of the side navigation menu which consists of a Ajax Accordion control inside a Collapsible Panel.

Since the collapsing of the Panel and the selecting of Accordion panes is all done via client-side javascript, there's no good way of maintaining the state of the menu when the user is redirected to another page (or clicks a link). To solve this, I added some additional javascript that is executed whenever the user manipulates the menu, that makes a callback which stores the state of the menu in a session variable (whether it's collapsed and what Accordion pane is selected). This way when the user is redirected, or clicks on a link to another page, I have the information necessary to make the side menu look the same as it did on the previous page.

And since, these two elements are shared among all the site's pages (via a MasterPage with a UserControl for each element)....I'm not sure what to do.

Also, the error still persists even after settingEnableViewStateMac="false"in the page directive....(not sure why this thread was marked resolved/answered, I know I didn't mark it that way...)


I tried it on both IE && FF like a hundred times, but still get no exception. May be I didn't click it quickly enough?

Based on my understanding, it may be caused by different requests and responses intersect.

Can you try to disable the button upon a click and enable it again after the callback returns to avoid this?


Thanks for the help, you do have to vary the frequency of your clicking to get it to throw the error. I know it sounds bizarre but I start with a few steady clicks, not even that fast, and then increase the frequency of clicks until the error is thrown. If it hasn't thrown the error after 50 clicks, I'll reload the page and try again (Here's a better YouTube video:http://www.youtube.com/watch?v=EBsMRxnOtpE).

Disabling the button after a click might work in the test scenario but my real world app initiates a callback whenever the user manipulates the navigation menu in some way. So, hindering their ability to quickly jump from one item in the menu to another may be problematic....though callback doesn't take long, sio it's something I'll look into more...

More importantly though, I'm not sure that solves the problem. In my real app the Timer for the UpdatePanel ticks every 60 seconds, while a callback is issued every time the navigation menu is manipulated. And, when I've seen the error thrown, it appears to be thrown by the ticking of the Timer, because I've received the error after I clicked on the menu a few times, and then did nothing, and the error would only popup when the Timer executed its next Tick event...

ConfirmButtonExtender does not validate prior to

Hi

I've got a scenario where we're using ConfirmButtonExtender on a button which needs to fire client-side validation prior to displaying the confirmation dialog (we're actually using a ModalPopExtender but have tried without). What's happening is that the confirmation dialog is showing but client-side validation is not firing until the user clicks OK in the popup. I've set ConfirmOnFormSubmit to True but it's not having the desired effect.

Another strange thing is that our ValidationSummary has ShowMessageBox enabled, but the popup that this normally shows is no longer being displayed, only the "*" next to each field on the form is. We're using an UpdatePanel on the page with all the above controls within it. The event handler for the confirm button click (the button assigned to ConfirmButtonExtender.TargetControlID) is calling Page.Validate and testing Page.IsValid during the asynch postback.

I suspect that I'm not quite using this combination of controls in the correct manner so any pointers most gratefully received.

Thanks

Ben

I've also had problems with this control when used on a button in a gridview. I know there was bug with it, just wondered if its been fixed.

My Page directives:

EnableEventValidation="false"AutoEventWireup="false"

<asp:GridViewID="dgDiets"runat="server"DataKeyNames="Pathway group code,Pathway type code"AutoGenerateColumns="False">

<Columns>

<asp:BoundFieldDataField="Pathway group code"HeaderText="Pathway group code"Visible="false"/>

<asp:BoundFieldDataField="Pathway type code"HeaderText="Pathway type code" />

<asp:BoundFieldDataField="Status"HeaderText="Status"/>

<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnDelete" CommandArgument="<%# Container.DataItemIndex %>" CommandName="DeleteRow" runat="server" Text="Delete" />
<cc1:ConfirmButtonExtender ID="ConfirmBtExt1"
runat="server" TargetControlID="btnDelete"
ConfirmText="Are you sure about deleting this record?" />
</ItemTemplate>
</asp:TemplateField>

</Columns>

<asp:GridView>

The following method should, but is not called when user clicks on ok popup:

Protected Sub dgDiets_OnRowCommand(ByVal etc, e as Sys.Web.UI.Webctrls.GridViewCommandEventArgs) Handles dgDiets.RowCommand

I'm sure this works on my home PC, but not at my work PC. However the code is identical. Anybody ever resolve this?

Thanks


Hi Egdif,

Egdif:

I've got a scenario where we're using ConfirmButtonExtender on a button which needs to fire client-side validation prior to displaying the confirmation dialog (we're actually using a ModalPopExtender but have tried without). What's happening is that the confirmation dialog is showing but client-side validation is not firing until the user clicks OK in the popup. I've set ConfirmOnFormSubmit to True but it's not having the desired effect.

Yes , the ConfirmButtonExtender will be shown when the associated Button is clicked. And the form is not going to be posted unless we click the ok button.Validators only work when the post is posting. So that's the problem.

Egdif:

Another strange thing is that our ValidationSummary has ShowMessageBox enabled, but the popup that this normally shows is no longer being displayed, only the "*" next to each field on the form is. We're using an UpdatePanel on the page with all the above controls within it. The event handler for the confirm button click (the button assigned to ConfirmButtonExtender.TargetControlID) is calling Page.Validate and testing Page.IsValid during the asynch postback.

I don't think you need to display another alert window. However, if you want to get the solution for your situation, we really need your source code.

I hope this help.

Best regards,

Jonathan

Wednesday, March 21, 2012

Compression does not work with UpdatePanel

Hi!

I'm using HttpModule for comression. Everything is well but client-side AJAX does not decompress response (after aynchronous request): error: "The message received from the server control could not be parsed."

Question 1: can I make AJAX to decompress asynch. responses ?

Question 2: can I make AJAX to decompress asynch.requests ?

<httpModules>

<addname="ScriptModule"type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

<addname="CompressionModule"type="WebSite.CompressionModule" />

</httpModules>

#region Using

using System;

using System.Web;

using System.IO;

using System.IO.Compression;

#endregion

namespace WebSite

{

///<summary>

/// Compresses the output using standard gzip/deflate.

///</summary>

publicclass CompressionModule : IHttpModule

{

publicvoid Init(HttpApplication context)

{

context.BeginRequest +=newEventHandler(context_BeginRequest);

}

privatevoid context_BeginRequest(object sender,EventArgs e)

{

HttpApplication app = (HttpApplication)sender;

if (app.Request.Url.ToString().ToLower().IndexOf("aspx") < 0)return;

string encodings = app.Request.Headers.Get("Accept-Encoding");

if (encodings ==null)return;Stream baseStream = app.Response.Filter;

encodings = encodings.ToLower();

if (encodings.Contains("gzip"))

{

app.Response.Filter =new GZipStream(baseStream,

CompressionMode.Compress);

app.Response.AppendHeader("Content-Encoding","gzip");

}

elseif (encodings.Contains("deflate"))

{

app.Response.Filter =new DeflateStream(baseStream,

CompressionMode.Compress);

app.Response.AppendHeader("Content-Encoding","deflate");

}

}

publicvoid Dispose()

{

}

}

Thank you for any help.

Andriy Zhornyk

Hi Andriy Zhornyk,

the best and practicable solution is to exclude the ajax related resources from your compression module. On the board ar some discussions about compression wirh ajax. AFAIK the most come to the same result, exclude the ajax resources from compression. In my compression module i do it win my configuration like this.

<HttpCompress compressionType="GZip"><ExcludedPathCollection><clear/><add path="WebResource.axd"/><add path="ScriptResource.axd"/><add path="*._AppService.axd"/></ExcludedPathCollection><ExcludedMimeTypeCollection><clear/><add mime="image/jpeg"/><add mime="image/gif"/><add mime="image/png"/><add mime="image/ico"/><add mime="application/binary"/></ExcludedMimeTypeCollection><ExcludedVariableCollection><clear/><add servervariable="http_x_microsoftajax"/></ExcludedVariableCollection></HttpCompress>

hope that help a little to find the right decision.


Thank you, but it's interesting for me to compress/decomress async postback data.

Is there such possibolity in MS Ajax?


That would be pretty difficult. The AJAX framework needs to be able to parse out the pipe delimited partial postback response. If it were compressed, you'd have to extend the PageRequestManager to handle that somehow.


I appreciate your answer but decompression on client is not impossible.

Have you seen "TeamPlain" solution from devBiz acquired by MS ? (web site for TFS:http://www.devbiz.com/downloads/TeamPlain-Web-2.0-RC.msi)

They managed to do it! Of course they didn't use MS Ajax but they compressed\decompressed async postbacks. The same thing I'm waiting from MS AJAX team. Because ZGipped page is very important for my customers' users with slow dialup internet...

I've been investigating MS AJAX Web.Extension source code and I think it's real to add compression\decompression features.

Is there anyone who managed this not simple task besides smart guys from devBiz?


If i understand you right is the way to go: compress(server) -> decompress(client). On callback: compress(client) -> decompress(server).

Well, i dont know enough over the architecture of the UpdatePanel to say it's possible or not. But from my point ist the only way to go a direct implementation in the UpdatPanel control or, if possible, create an adapter.

Anyway, maybe one from the ajax extension dev team is able to enlighten us about the possibility of this way.


I've faced similar situation , i am using update panel and http compression. My workarund is to not compress/decompress async postback. I just adding some additional checking like this :
if(Context.Request.Params["HTTP_X_MICROSOFTAJAX"] == null)
{
DoCompress();
}

regards ,
yose r