Often we need to store some client-side data from request to request. Because the browser supports two simultaneous connections to the server it's easy to do two concurrent requests to the server - and when response is received we want to somehow differentiate between that requests. For example when I click on Button1 - I want to pass let's say exact time when request was invoked, or some javascript object on which I need to perform some actions in endRequestHandler.
So what I want to do - attach some javascript object to the request somehow, to later use it when that request is served by the server and response is sent back. At the same time I don't want to sent that attached object to the server with request and then receive it from the server, because it's not efficient - we can store that object on client side.
To do this I will use userContext Property of WebRequest Class in ASP.NET AJAX library.
I created the sample page. The code looks like:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> <style type="text/css"> .loggerDiv { width: 200px; height: 400px; overflow: auto; float: left; border: solid 1px black; padding: 3px; } </style> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> <script type="text/javascript"> var loggerObj = new Logger(); function beginRequestHandler(sender, args) { // get WebRequest object var request = args.get_request(); // get button that invoked postBack var clickedButton = args.get_postBackElement(); var customData = { requestStart:new Date(), button:args._postBackElement }; // modify WebRequest, assigning custom data to _userContext property request.set_userContext(customData); }; function endRequestHandler(sender, args) { var response = args.get_response(); if(response.get_responseAvailable()) { // get associated WebRequestObject var webRequest = response.get_webRequest(); // get custom data we assigned to WebRequest earlier var customData = webRequest.get_userContext(); if(customData.button && loggerObj) { var loggerDiv; if(customData.button.attributes.getNamedItem("logger")) { loggerDiv = customData.button.attributes.getNamedItem("logger").value; var sb = new Sys.StringBuilder(); sb.append("----------------" + "<br />"); sb.append("request start: "+customData.requestStart.toTimeString() + "<br />"); sb.append("request end: "+new Date().toTimeString() + "<br />"); sb.append("request invoked by: "+customData.button.id + "<br />"); // display registered dataItems sb.append("Data items:" + "<br />"); var dataItemKey = ""; for(dataItemKey in sender._dataItems) { sb.append(dataItemKey + ": " + sender._dataItems[dataItemKey]+"<br />"); } sb.append("----------------" + "<br />"); loggerObj.log(loggerDiv, sb.toString()); } } } }; function Logger(divId) { // logs a message into div this.log = function(logger, message) { if($get(logger)) { $get(logger).innerHTML += message + "<br />"; $get(logger).scrollTop = $get(logger).scrollHeight - 400; } }; this.clearLog = function(logger) { if($get(logger)) { $get(logger).innerHTML = ""; } }; }; </script> <asp:UpdatePanel runat="server" ID="UP"> <ContentTemplate> <asp:Button ID="Button1" logger="logger1" runat="server" Text="Button1" onclick="Button1_Click" /> <asp:Button ID="Button2" logger="logger2" runat="server" Text="Button2" onclick="Button2_Click" /> <asp:Button ID="Button3" logger="logger3" runat="server" Text="Button3" onclick="Button3_Click" /> <asp:Button ID="Button4" logger="logger4" runat="server" Text="Button4" onclick="Button4_Click" /> </ContentTemplate> </asp:UpdatePanel> <div> <div id="logger1" class="loggerDiv"> </div> <div id="logger2" class="loggerDiv"> </div> <div id="logger3" class="loggerDiv"> </div> <div id="logger4" class="loggerDiv"> </div> </div> </div> </form> <script type="text/javascript"> Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler); Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequestHandler); </script> </body> </html>
Code behind:
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; using System.Threading; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Thread.Sleep(100); } protected void Button1_Click(object sender, EventArgs e) { ScriptManager1.RegisterDataItem(this, "Button1 - confirmed from the server"); } protected void Button2_Click(object sender, EventArgs e) { ScriptManager1.RegisterDataItem(this, "Button2 - confirmed from the server"); } protected void Button3_Click(object sender, EventArgs e) { ScriptManager1.RegisterDataItem(this, "Button3 - confirmed from the server"); } protected void Button4_Click(object sender, EventArgs e) { ScriptManager1.RegisterDataItem(this, "Button4 - confirmed from the server"); } }
The most important in this code is how we attach custom object in beginRequestHandler:
var request = args.get_request();
request.set_userContext(customData);
And how we retrieve it later:
var response = args.get_response();
var webRequest = response.get_webRequest();
var customData = webRequest.get_userContext();
As you can see I am attaching DataItems to asynchronous responses - this is just demonstration of how can we pass some additional data from server, that can be tracked trough
sender._dataItems
property in endRequestHandler.
Not hard to do at all.
You can see online sample.
Also you can download source code for this sample here.
Hope this helps.
1 comment:
Graciaaaaaaaaas!! So many thankyouuuu! i spent months to resolve the #$&% sys undefined problem.
Post a Comment