ASP.Net 2.0 Client Callbacks, makes remote scripting easier

来源:互联网 发布:中上社会地位 知乎 编辑:程序博客网 时间:2024/05/01 09:13
 

During November last year, I wrote an article about Clinet callbaks with Asp.Net 2.0. I have now updated this article for the May CTP version of VS 2005), so here is he updated version:

 

How many of you have used technologies to call server-side code from a client-side code? I think a lot of you have tried some of the technologies that has bean available in the past few years for making client-side code to call server-side code. If we take a few steps back in time, there have been different kinds of technologies of making remote calls from a client to a server. I will not mention all of them; instead I will focus on one most common used technology. I think all of you have heard about Remote Scripting. With Remote Scripting we were able to make client-side calls from a page to server-side script located in an Active Server Pages (ASP) without having to submit the page. The Remote Scripting technology uses a Java Applets to make the communications to the server. The applet communicates with the server over the HTTP protocol and wrapped the data in some sort of XML. To use Remote Scripting we needed two files, one that handles the client side request (rs.htm) and one for firing the code on the server side (rs.asp). With ASP.NET 2.0 “codename Whidbey” there is a new technology for making remote call possible. This new technology is called Client callbacks.

 

With Client callbacks we can make client-side script to call server-side events without causing a postback. This will be a perfect solution for situations like executing server-side code without refreshing the page, preloading of data and validations etc. This new callbacks technology is very similar to Remote Scripting, but instead of using a Java applet Client callbacks uses XmlHTTP to communicate with the server, and instead of the rs.htm and rs.asp file ASP.Net 2.0 uses the a script-library named CallBackManager.

 

Note To use Client callbacks, XmlHTTP must be supported by the browsers. There is a new properties added to the HttpBrowserCapabilities class that could be used to check if the browser support Client callbacks—SupportsCallBack.

 

How does the Client call backs work

 

The client makes the call of a client-side method that will use the CallBackManager. The CallBackManager creates the request to an .aspx page on the server. The server processes the page and its events and makes the call of the sever-side function. The CallBackManager then parses the server response and make the call to a callback method located on the client-side. The CallBackManager must know the name of the client-side callback method. The CallbackManager must know which method it should call on the client-side. This is accomplished by using the GetCallBackEventReference method of the page. With this method we could also specify which method the CallbackManager should call if the server throws an exception.

 

Let’s see how callbacks can be implemented. The following example that I’m going to describe will use callbacks to validate if a number between 1 and 1000 is entered into a textbox. The code for this is shown in Code Sample 1.

 

Code Sample 1. default.aspx

 

<%@ page language="C#" %>

<%@ implements interface="System.Web.UI.ICallbackEventHandler" %>

 

<script runat="server">

 

    public string RaiseCallbackEvent(string eventArgs)

    {

        try

        {

            int value = Int16.Parse(eventArgs);

       

            if( value >= 1 && value <= 1000 )

                return "You entered the number: " + eventArgs;

            else

                return "Please enter a number between 1 and 10000";

        }

        catch

        {

            throw new ApplicationException("You must enter a number.");

        }

    }

  

    public void Page_Load(object sender, EventArgs e)

    {

       

        if (!Request.Browser.SupportsCallBack)

                      throw new ApplicationException("This browser doesn’t support Client callbacks.");

 

        string src = Page.GetCallbackEventReference(

                                   this,

                                   "arg",

                                   "ClientCallback",

                                   "ctx",

                                   "ClientErrorCallback");

 

        string mainSrc = @"function ValidateNumber(arg, ctx)

                           { " + src + "; }";

 

        Page.ClientScript.RegisterClientScriptBlock(

                                   this.GetType(),

                                   "ValidateNumber",

                                   mainSrc,

                                   true);

    }

 

</script>

 

<html>

<head runat="server">

    <title>Untitled Page</title>

   

    <script language="javascript">

   

        function Validate()

        {

            var n = document.forms[0].txtNumber.value;

            ValidateNumber(n, "txtNumber");

        }

       

        function ClientCallback( result, context )

        {

            alert(result);

        }

       

        function ClientErrorCallback( error, context )

        {

            alert("The validation failed. " + error);

        }

   

    </script>

 

</head>

<body>

    <form runat="server">

      Please enter a number between 1 and 1000:<br />

      <input id="txtNumber" name="txtNumber" type="text"/>

      <button id="butVaidate" OnClick="Validate()">Validate</button>

    </form>

</body>

</html>

 

Let’s break the important part of the code into peaces and explain them step by step.

 

<%@ page language="C#" %>

<%@ implements interface="System.Web.UI.ICallbackEventHandler" %>

 

The System.Web.UI.ICallbackEventHandler must bee implemented for using callback events. This interface could also be implemented by controls, such as Buttons, TextBoxes etc.

 

The ICallbackEventHandler has one method that must be implemented for making callback works—RaiseCallbackEvent. This method takes one argument which will contain the data from the client, and return a string value back to the client. In the previous sample the RaiseCallbackEvent will check if the argument (eventArgs) is numeric value, if not an exception is thrown. If the argument is a numeric value, the method will check if the value is between 1 and 1000. If not a message that tells us to enter a value between 1 and 1000 will be returned. If the argument contains a correct value, the value will be returned.

 

public string RaiseCallbackEvent(string eventArgs)

 

The following code will check if the browser supports client callback, if not an exception will be thrown.

 

if (!Request.Browser.SupportsCallBack )

                      throw new ApplicationException("This browser doesn’t support Client callbacks.");

 

The next step is to set a reference to the control that has implemented the ICallbackEventHandler interface. This is required for the callbacks should know which client-side callback method should be called. To add a reference, the GetCallbackEventReference method of the Page object will be used. GetCallbackEventReference has three overloaded methods:

 

public string GetCallbackEventReference(

           Control control,

           string argument,

           string clientCallback,

           string context)

 

public string GetCallbackEventReference(

           Control control,

           string argument,

           string clientCallback,

           string context,

           string clientErrorCallback)

 

public string GetCallbackEventReference(

           string target,

           string argument,

           string clientCallback,

           string context,

           string clientErrorCallback)

 

For description of the GetCallbackEventReference arguments see table 1.

 

Table 1. GetCallbackEventReference arguments.

Argument

Description

control

The controls that implements ICallbackEventHandler

target

If no control is specified this would be the ID of a control that implements the ICallbackEventHandler.

argument

The value that will be sent to the RaiseCallbackEvent.

clientCallback

The name of the client-side callback method.

context

A value that will be passed back from the client-side event to the client-side callback method.

clientErrorCallback

The name of the client-side error callback method. This method will be executed if the server thrown an exception.

 

The following code uses the GetCallbackEventReference to specify the client-side callback methods and the control that implements ICallbackEventHandler. In this example it’s the current page that has implemented the ICallbackEventHandler. So the current page object is passed to the method. When the server-side method has been executed the ClientCallback method on the client-side will be executed. If the servers throw an exception, the ClientErrorCallback will be executed on the client-side. The arg and ctx are names of the arguments of the client-side event that calls the server-side method. This event is created as a string and added to the mainSrc variable in this code snippet—ValidateNumber.

 

public void Page_Load(object sender, EventArgs e)

{

   string src = Page.GetCallbackEventReference(

                                   this,

                                   "arg",

                                   "ClientCallback",

                                   "ctx",

                                   "ClientErrorCallback");

 

    string mainSrc = @"function ValidateNumber(arg, ctx)

                           { " + src + "; }";

 

The ValidateNumber event must be added to the client as a client-side script, so it could be called by client-side methods or via a control’s event. In the current version of ASP.Net 1.x, client-side scripts could be added to a page with the RegisterClientScriptBlock and RegisterStartupScript methods, those are accessible through the Page object. Those methods will still work in ASP.Net 2.0 for backward compatibility, but this example will use the new ASP.Net 2.0 RegisterClientScriptBlock method to add the client-side script to the client. The new method is accessible through the current Page class new ClientScript property (ClientScriptManager). The RegisterClientScriptBlock in the current ASP.Net 1.x version takes two arguments, a unique key to identify the script block and a script string with the client-side script. The new method can take two more arguments, see table 2. The new RegisterClientScriptBlock has two overloaded methods:

 

Public void RegisterClientScriptBlock(

                           Type type,

                           string key,

                           string script)

 

Public void RegisterClientScriptBlock(

                           Type type,

                           string key,

                           string script,

                           bool addScriptTags)

 

Table 2. RegisterClinetScriptBlock arguments

Argument

Description

Type

A type, so the same key could be used twice.

Key

A unique key to identify the script block.

Script

The script block to be added to the client.

addScriptTages

Allows the method to insert the <script> tag.

 

The client-side method that will call the server is registered with the new ReisgterClientScriptBlock method.

 

 Page.ClientScript.RegisterClientScriptBlock(

                                   this.GetType(),

                                   "ValidateNumber",

                                   mainSrc,

                                   true);

 

The ReisterClientScriptBlock above will generate:

 

function ValidateNumber(arg, ctx)

{

     __doCallback('__Page',arg,ClientCallback,ctx,ClientErrorCallback);

}

 

This __doCallback method takes five arguments, the current page, the argument value sent into the RaiseCallbackMethod, the client-side callback method, the context value that will be sent to the client-side callback method, and the last argument is the client-side method that will be triggered if the server throws an exception.

 

The ___doCallback method could directly be fired through a client-side function or directly triggered from a client-side control event, such as onClick event of a button. In this example, the __doCallback will be triggered through the ValidateNumber method.

 

Let’s take a look the client-side callback methods. The Validate method will be triggered by the button control onClick event. This method will get the value entered in the txtNumber textbox control and pass is as an argument through the arg argument of the ValidateNumber method that was previously described. The Validate method will also pass the id of the textbox control through the context argument of the ValidateNumber method (the value of the context argument will be sent to the client-side callback methods). ClientCallback will take two arguments and it’s the result returned from the RaiseEventCallback method and the context passed through the ValidateNumber method. The ReiseEventCallback will be triggered when the server has done its request and display the returned value in a message box. If the server throws an exception the ClientCallErrorCallback method will be trigged and the error message return from the RaiseErroEventCallback will be displayed in a message box.

 

function Validate()

{

   var n = document.forms[0].txtNumber.value;

   ValidateNumber(n, "txtNumber");

}

       

function ClientCallback( result, context )

{

   alert(result);

}

      

function ClientErrorCallback( error, context )

{

   alert("The validation failed. " + error);

}

 

The Validate method is hooked up to a button’s onClick event. So when the button is pressed the Validate method is triggered and the server-side code will be executed.

 

<form runat="server">

      Please enter a number between 1 and 1000:<br />

      <input id="txtNumber" name="txtNumber" type="text"/>

      <button id="butVaidate" OnClick="Validate()">Validate</button>

</form>

 

Let’s take a look at the example in action. When the example above is running a page with a textbox and a button will be displayed. The page will also prompt us to enter a number between 1 and 1000. When the validate button is pressed a client callback will be performed. The code on the server-side will check if a correct number is entered, and if not the sever-side method will return a message that tells us to enter a number between 1 and 1000. If we enter a non-numeric value, an exception will be thrown and the error method specified by with the GetCallBackEventReference will be called on the client. The client-side method will show the error returned from the server in a message box.

原创粉丝点击