Client API-Enabled DotNetNuke Controls


Client API's Callback

As you've seen, one of the best reasons for learning and making use of the Client API is to improve the end-user experience. Minimizing postbacks to the server was identified earlier as one of the goals that would help you achieve an improved end-user experience. Thus far this has been accomplished by sending client-side variables to the client that can be manipulated and returned to the server-side code, in a format it can read, when a postback occurs. This helps minimize postbacks because the client side handles the client-side events — such as expanding — raised in the DotNetNuke Tree example. The control changes, the changes are saved to a variable, and then the variable is processed when the client side finally communicates with the server side.

The question you are probably asking yourself now is, "What if I want to communicate with the server-side code more often without causing a postback?" Unless you are just beginning web development, you have probably heard some hype lately about Ajax and Atlas. Although the buzz about them is relatively new, the concept behind them has been around since the late '90s. Most of the reason for the hype now is probably because communication between the server-side and client-side code without requiring a postback — which Ajax and Atlas offer — is becoming easier to do and therefore more web sites are making use of it. However, to answer the question asked at the beginning of this paragraph, the answer is asynchronous callbacks. These callbacks enable communication between the client side and server side without the need for a postback.

Life Cycle of a Client Callback

When you're working with the Client API and Client Callback, it is just as important to understand the callback life cycle as it is to understand the page life cycle when dealing with view state. The remainder of this section is broken down into the steps within the Client Callback life cycle and describes what happens at each phase. Figure 10-2 illustrates the main areas of interest in the Client Callback lifecycle.

image from book
Figure 10-2

Setup and Registration

To get started using callbacks, the first thing you must do is implement IClientAPICallbackEventHandler in the page or your control. In the earlier example of the DotNetNuke Tree control, this was handled for you. After implementing the handler, you have to obtain JavaScript to invoke a callback. This is done by making a call to the GetCallbackEventReference method. The parameters required when calling the method are described in Table 10-1.

Table 10-1: GetCallBackEventReference Parameters

Argument

Description

ObjControl

The control that is responsible for handling the callback. It must implement IClientAPICallBackEventHandler.

StrArgument

The string is evaluated on the client side and is passed to the server-side callback handler.

strClientCallback

The pointer to the client-side function that is to be invoked when a callback is successful and complete.

strContext

The string is evaluated on the client side and passed to the client-side callback methods.

strErrorClientCallback

The pointer to the client-side function that is invoked when a callback errors out.

The result of this method will be JavaScript that needs to be assigned to the client-side event handler. After you have completed this, you would normally have to write logic to handle potential callbacks. This must be done early on in the page's life cycle, such as in the Page_Init, so that no response is written back other than the result of the callback. You handle potential callbacks by calling the HandleClientAPICallbackEvent method and passing it the Page object, as shown in Listing 10-9. When working on a DotNetNuke project making use of callbacks, it is not necessary to write this logic because it is already handled by the code in default.aspx.vb.

Listing 10-9: Handling Potential Callbacks in Page_Init

image from book
 ' ClientCallback Logic DotNetNuke.UI.Utilities.ClientAPI.HandleClientAPICallbackEvent(Me) 
image from book

It is assumed that prior to completing this phase in the callback life cycle, the proper namespaces and variables discussed in the "Using the DotNetNuke Client API" section have been registered. For callbacks, specifically, it requires the registering of the dnn.xmlhttp client-side namespace. Note that if you are making a call to the GetCallbackEventReference method, the registering of the dnn.xmlhttp client-side namespace will be handled for you. Now, after registering the client-side namespace and setting up the server side for handling any potential callbacks, you need to implement the IClientAPICallbackEventHandler interface. When implementing an interface in your page or control, you must also implement the methods contained within it. The IClientAPICallbackEventHandler interface contains only a single method, RaiseClientAPICallbackEvent. This function needs to be passed the eventArgument variable, which is some data returned from the client side, as a string. An example of implementing the RaiseClientAPICallb kEvent method is shown in Listing 10-10.

Listing 10-10: RaiseClientAPICallbackEvent Function

image from book
 Public Function RaiseClientAPICallbackEvent(ByVal eventArgument As String) image from book As String Implements DotNetNuke.UI.Utilities.IClientAPICallbackEventHandler. image from book RaiseClientAPICallbackEvent Return "Hello World! " & eventArgument End Function 
image from book

Essentially, this function is on the server side waiting for the client side to make a callback. When a callback is made, the function grabs the variable passed to it and returns a string as its result. What is done with the result after it's returned to the client side is up to the developer. In most situations, you will present users with some type of notification that their callback is complete and show them any necessary changes or errors that were a result of it

If your only goal is to implement client callbacks, you need go no further. Everything required to get going has been covered. The remaining steps in the life cycle are handled via the Client API and should be reviewed for a better understanding of what is actually done by the Client API.

Client-Side Handling of the Callback

In the client-side handling of the callback, all variables are on the client side along with the necessary script files. One of the client-side namespaces that was required to be registered is the dnn.xmlhttpnamespace. That's because the script contains the client-side function necessary to create a callback to the server side from the client side. The client-side code function, named doCallBack, is shown in Listing 10-11.

Listing 10-11: dnn.xmlhttp.doCallBack Client-Side Function

image from book
 dnn_xmlhttp.prototype.doCallBack = function(sControlId, sArg, pSuccessFunc, image from book sContext, pFailureFunc, pStatusFunc, bAsync) {    var oReq = dnn.xmlhttp.createRequestObject();    var sURL = document.location.href;    oReq.successFunc = pSuccessFunc;    oReq.failureFunc = pFailureFunc;    oReq.statusFunc = pStatusFunc;    oReq.context = sContext;    if (bAsync == null)       bAsync = true;    if (sURL.indexOf('.aspx') == -1)   //fix this for url's that dont have page name in them...  quickfix for now...       sURL += 'default.aspx';    if (sURL.indexOf('?') == -1)       sURL += '?';    else       sURL += '&';    //sURL += '__DNNCAPISCI=' + sControlId + '&__DNNCAPISCP=' + image from book encodeURIComponent(sArg);    oReq.open('POST', sURL, bAsync);    //oReq.send();    if (encodeURIComponent)       sArg = encodeURIComponent(sArg);    else       sArg = escape(sArg);    oReq.send('__DNNCAPISCI=' + sControlId + '&__DNNCAPISCP=' + sArg); } 
image from book

As demonstrated in Listing 10-11, the first thing this client-side function does is create a newXmlhttpRequestObject by calling the createRequestObject function , which is located in the same client-side namespace. createRequestObject is responsible for determining the callback method supported by the user's browser. After XmlhttpRequestObject is created, this method assigns the pointers to the client-side function for success and the client-side function for failure. These function names, along with other important parameters passed in to the doCallBack client-side function, are described in Table 10-2.

Table 10-2: Important doCallBack Parameters

Argument

Description

sControlId

The control that is responsible for handling the callback. It must implement IClientAPICallBackEventHandler.

pSuccessFunc

Stores a pointer to the function to be invoked upon a successful request.

pFailureFunc

Stores a pointer to the function to be invoked upon a failed request.

sContext

Stores the context of the request to be passed along to the success/failure function.

Note 

If the current browser type does not support the XmlHttp request, it will use the JsHttp request that is referred to as the IFRAME request. Most browsers support XmlHttp requests, but this is worth mentioning.

When the XmlHttp request object is created, the return URL for the request is set, the XmlHttp request object is opened, and communication with the server side begins using the XmlHttp request object's send function. At the end of this phase in the callback life cycle, focus is switched to the server side again.

Page_Init Handling of Callback Requests

Earlier in this chapter, you reviewed the life cycle of the page and were able to see how view state was involved at the various phases of the life cycle. This not only helps you understand the behavior of postbacks, but it also aids in clarifying things at this point in the callback life cycle.

The main reasons for handling callbacks in the Page_Init is that it is not possible to handle this any sooner in the life cycle of the page. Prior to this phase in the page life cycle, the controls on the page are not loaded yet. If the controls are not loaded yet, the page will not be able to use the FindControl method on them because prior to this phase there are no controls. On the other hand, you should not attempt to handle this later in the page life cycle than Page_Init because there is a chance some unwanted response text may be generated. As Listing 10-9 showed, the Startup and Registration phase of the callback life cycle is handled for you by DotNetNuke in its default.aspx.vb code.

Handle the Client API Callback Event

Part of handling the callback request is passing the request to the server-side callback event. The HandleClientAPICallbackEvent method, located within the ClientAPI.vb file, is now invoked and is responsible for creating a new ClientAPICallbackResponse object. With the new ClientAPICallbackResponse object created, the first order of business is to determine if certain criteria are met. The criteria are that the control must exist and be located on the server side, and the IClientAPICallbackEventHandler interface must be implemented. If those are met, the RaiseClientAPICallbackEvent method is called and a response and status code must be assigned.

ClientAPICallbackResponse ultimately reports back this status code and response from the server to the client side. The available status codes to return back to the client side are shown in Listing 10-12. Also handled in the ClientAPICallbackResponse, but not discussed, is how the response will be sent. This is either in the XmlHttp or JsHttp format, which is determined based on how the data was received from the client.

Listing 10-12: Callback Response Status Code Enumerator

image from book
 Public Enum CallBackResponseStatusCode OK = 200       GenericFailure = 400       ControlNotFound = 404       InterfaceNotSupported = 501 End Enum 
image from book

If the format is XmlHttp, which it normally is, the response appends the header of the page. If not, a Response.Write is added to the page.

Callback Response Handling

It is recommended, but not required, that callbacks be handled asynchronously. If they are not handled asynchronously, though, the browser won't be usable while it is checking for a callback. When that happens, it may appear to the end user that the browser is locked, which leads to confusion and lessens the end-user experience.

When a response is returned to the client side, it needs to be received by an event handler. This requires an event handler to be registered on the client side when the page is loaded. The responsibility of this client-side event handler is to determine if the callback was successful or if it failed. Listing 10-13 demonstrates how this is handled on the client side.

Listing 10-13: XmlHttpRequest's Client-SideComplete Function

image from book
 dnn_xmlhttp.prototype.XmlHttpRequest.prototype.complete = function (sRes) {    var sStatusCode = this.getResponseHeader('__DNNCAPISCSI');    this.completed=true;    if (sStatusCode == '200')       this.successFunc(sRes, this.context);    else    {       var sStatusDesc = this.getResponseHeader('__DNNCAPISCSDI');       if (this.failureFunc != null)          this.failureFunc(sStatusCode + ' - ' + sStatusDesc, this.context);       else          alert(sStatusCode + ' - ' + sStatusDesc);    } } 
image from book

Inside the complete method, the status code and status description are obtained by calling the getResponseHeader method. This method reads the response that was written on the server side to the header of the current page. If the JsXmlHttpRequest object was being used instead of the XmlHttpRequest object, its complete method would read the textbox's value from the IFRAME document that matches the header name.

Using either of the request object types works the same after reading the value from the server side. If the function is successful, it is passed to the success function that was assigned during the registration phase of the life cycle. If the function was anything other than successful, the client-side failure method — if one exists — is invoked.

The life cycle of a callback is now complete. You probably noticed that the majority of this is handled for you when using DotNetNuke. If you only want to use the current set of DotNetNuke Client API-enabled controls, which is discussed next, only a minimal understanding of this life cycle is required. However, if you want to extend the Client API or make web controls of your own, you'll need a solid understanding of the life cycle to efficiently achieve a proper end result.




Professional DotNetNuke 4.0 (c) Open Source Web Application Framework for ASP. NET 4.0
Professional DotNetNuke 4: Open Source Web Application Framework for ASP.NET 2.0 (Programmer to Programmer)
ISBN: 0471788163
EAN: 2147483647
Year: 2006
Pages: 182

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net