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.
Graciaaaaaaaaas!! So many thankyouuuu! i spent months to resolve the #$&% sys undefined problem.
ReplyDelete