|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
This article is written by Marcin Kawalerowicz and was originally published in the September 2005 issue of the Software Developer's Journal. You can find more articles at the SDJ website. IntroductionImagine a sophisticated website: a fancy navigation system, menu, footer, language selection, logo, tabs... The page weighs a whole lot as it is and, on top of that, we have to reload the contents of the one and only drop-down list from our database. What does that mean to our ASP.NET application? First, a query sent to the server, then the processing and sending of the response to the browser, where the time-consuming page rendering process will take place. Up to several tens of seconds (!) to only to reload the values of a single drop-down list? It does not have to be that way because this is where Remote Scripting, which is basically a way of remote procedure calling on a server, comes in. Remote Scripting is not the first idea that came up to minimize the undesired effects of time consuming page reloading. Apart from techniques which encapsulate parts of a site in autonomic frames, it is a common practice to buffer information necessary for future updates of various DHTML elements. The data is being sent to the browser right in the source code of the page. Necessary information can be saved in invisible Different kinds of Remote Scripting systems can be used in an attempt to solve this difficult situation. They can perform remote server function calls from the browser level. This allows to save the time necessary to completely resend and build a page due to a query working somewhere in the background and supplying small amounts of data at a time. Microsoft has presented the first technology of this kind by releasing the free Remote Scripting system – MSRS. Although the system was capable of synchronous and asynchronous operation, it never gained much popularity among non-corporate users. This is due to the fact that it forces users to use a Java applet, is compatible only with the Windows platform, and is incompatible with most browsers. Naturally, MSRS also requires IIS to be running on the server side. The interesting fact is that Brent Ashley came to the programmer's to rescue by publishing a fairly decent JSRS library system, which is compatible with many browsers. On the client side, it uses JavaScript, and works only in asynchronous mode. Through the years, several server side library implementations have been created, including those for CGI, ASP, servlets, PHP, etc. A JSRS version, together with a library working in ASP.NET, has been presented by Alvaro Mendez. The library cooperates with both JSRS and MSRS (this one as well – it halts all browser actions until a response from the server is obtained). First, we will try it out by writing a simple calculator, and then by solving the aforementioned automobile problem. InstallationEquipping your ASP.NET site with the functionality allowing it to remotely invoke methods on the server from the browser's JavaScript level is very simple. Let us copy the AMS.Web.RemoteScripting.dll library to the bin folder of our Internet application (or set the proper file reference in Visual Studio). In the if (AMS.Web.RemoteScripting.InvokeMethod(Page))
return;
The server is ready to accept queries. Let us prepare the client by declaring the usage of the rs.js file as follows: <script language="'JavaScript'" src='rs.js'></script>
This is all that needs to be done from the “administrative” point of view. Now we have to program the methods. Simple trainingOur goal is to create a simple calculator on a web site. It will be able to perform one of four basic arithmetical operations on two given numbers. The calculations will be carried out on the server side. Let us prepare a page, such as the one in the example in Listing 1. Listing 1. Page code for a simple calculator <FORM ID="Form1" METHOD="post" RUNAT="server">
<INPUT id="p1" type="text" size="10">
<SELECT id="operation">
<OPTION selected value="add">+</OPTION>
<OPTION value="sub">-</OPTION>
<OPTION value="mul">*</OPTION>
<OPTION value="div">/</OPTION>
</SELECT>
<INPUT id="p2" type="text" size="10">
<INPUT id="b" type="button" value="=" onclick="MakeOperation()">
<DIV id="result"></DIV>
</FORM>
Clicking the [=] button calls the Listing 2. The calculator's JavaScript function function MakeOperation()
{
RS.Execute(
"Calculator.aspx",
"MakeOperation",
document.Form1.operation.options[
document.Form1.operation.selectedIndex
].value,
document.Form1.p1.value,
document.Form1.p2.value,
SetResult,
ErrorCallback);
}
function SetResult(res)
{
result.innerHTML = res;
}
function ErrorCallback(res)
{
alert("Error: "+res);
}
Programming the method on the server comes down to defining the Listing 3. The calculator public double MakeOperation(
string operation,
string p1,
string p2)
{
double d1 = Convert.ToDouble(p1);
double d2 = Convert.ToDouble(p2);
double output = 0;
switch(operation)
{
case "add":
output = d1 + d2;
break;
case "sub":
output = d1 - d2;
break;
case "div":
output = d1 / d2;
break;
case "mul":
output = d1 * d2;
break;
}
return output;
}
The automobile riddleLet us now attempt to solve the problem of the three drop-down lists presented at the beginning of the article. We want to create the dream car for ourselves. First, we will choose the make, then the type of the car, and finally decide on the model. In the classical solution, each decision requires the entire page to be reloaded. We will use Remote Scripting to download only the data that we really need. Let us prepare the aspx page as shown in Listing 4. Listing 4. Dream Car Configuration <%@ Page language="c#" Codebehind="Cars.aspx.cs"
AutoEventWireup="false" Inherits="JSRS.Cars" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<title>RS Cars</title>
<script language="javascript" src="scripts/rs.js"></script>
<script language="JavaScript">
function LoadModel()
{
RS.Execute("Cars.aspx",
"GetModel",
document.Form1.ddlMake.value,
RS.ReplaceOptions2,
document.Form1.ddlModel);
dcument.Form1.ddlType.options.length = 0;
}
function LoadType()
{
RS.Execute("Cars.aspx",
"GetType",
document.Form1.ddlModel.value,
RS.ReplaceOptions2,
document.Form1.ddlType);
}
</script>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:dropdownlist id="ddlMake" runat="server">
</asp:dropdownlist><br>
<asp:dropdownlist id="ddlModel" runat="server">
</asp:dropdownlist><br>
<asp:DropDownList id="ddlType" runat="server">
</asp:DropDownList><br>
<asp:Button id="btnCheck" runat="server"
Text="Check" Width="96px"></asp:Button><br>
<asp:Label id="lblMake" runat="server">
Make ID:</asp:Label><br>
<asp:Label id="lblModel" runat="server">
Model ID:</asp:Label><br>
<asp:Label id="lblType" runat="server">
Type ID:</asp:Label>
</form>
</body>
</html>
We will use a simple XML file as our database. We can load it into the Listing 5. Loading data from an XML file into our session private DataSet ds
{
get
{
if (Session["ds"] != null)
return (DataSet)Session["ds"];
else
{
ds = new DataSet();
ds.ReadXml(MapPath("Cars.xml"));
Session["ds"] = ds;
return ds;
}
}
set { Session["ds"] = value; }
}
We will declare the usage of Remote Scripting in the ddlMake.Attributes.Add("onchange","LoadModel()");
ddlModel.Attributes.Add("onchange","LoadType()");
When the page is first loaded, we tie the Make table, which represents the make of the car, to the first drop-down list. ddlMake.DataSource = ds.Tables["Make"];
ddlMake.DataTextField = "MakeName";
ddlMake.DataValueField = "MakeID";
ddlMake.DataBind();
The library contains a useful function for processing results: <option value='x'>y</option>
<option value='x'>y</option>
<option value='x'>y</option>
...
Let us, therefore, prepare such methods for the Type and Model tables. They will return a list of car types for a given make and a list of models for a given type (Listing 6). Listing 6. Remote server-side methods public string GetModel(string MakeID)
{
string output = "<option value='-1'></option>";
foreach (DataRow row in
ds.Tables["Model"].Select("MakeID='" + MakeID + "'"))
output += "<option value='" + row[0] + "'>" +
row[2] + "</option>";
return output;
}
public string GetType(string ModelID)
{
string output = "<option value='-1'></option>";
foreach (DataRow row in
ds.Tables["Type"].Select("ModelID='" + ModelID + "'"))
output += "<option value='" + row[0] +
"'>" + row[2] + "</option>";
return output;
}
Unfortunately, drop-down lists populated at the client side lose all their contents as soon as the page is reloaded (that is why one should not place them in the page's ViewState). Therefore, we must set them again each time. To do this, we can use the Listing 7. Repeated loading of list contents ddlModel.DataSource = new DataView(ds.Tables["Model"],
"MakeID='" + ddlMake.SelectedValue +
"'", null, DataViewRowState.CurrentRows);
ddlModel.DataTextField = "ModelName";
ddlModel.DataValueField = "ModelID";
ddlModel.DataBind();
ddlModel.Items.Insert(0, new ListItem("","-1"));
ddlModel.SelectedValue = Request["ddlModel"];
ddlType.DataSource = new DataView(ds.Tables["Type"],
"ModelID='" + ddlModel.SelectedValue +
"'", null, DataViewRowState.CurrentRows);
ddlType.DataTextField = "TypeName";
ddlType.DataValueField = "TypeID";
ddlType.DataBind();
ddlType.Items.Insert(0, new ListItem("","-1"));
ddlType.SelectedValue = Request["ddlType"];
How does this work?While preparing remote method calls, the client side script opens an invisible container. Most often, it is a floating GET /RSASP/Calculator.aspx?RC=C1&M=MakeOperation&P0=[mul]
&P1=[2]&P2=[3]&U=1119008434742 HTTP/1.1
Subsequent parameters signify the protocol ( On the server sideBy means of reflection, the library finds the required ( <html>
<body onload="p=document.layers?parentLayer:window.parent;
p.RS.pool['C1'].setResult(true);">Payload:<br>
<form name="rsForm"><textarea rows="4" cols="80"
name="rsPayload">2</textarea></form>
</body>
</html>
This code calls the SummaryRemote Scripting is one of the ways the World Wide Web might follow. This tendency is clearly shown by the Script Callback technology, which will be part of the second version of the .NET Framework. One can only hope that, as this technology becomes more popular, the way people look at web site programming will change. Time will show. In the mean time, the library created by Alvaro Mendez can be used today to speed up the WWW. Info on the 'Net
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||