Ajax-canceling server tasks

Source: Internet
Author: User
Use ASP. net ajax to cancel server tasks

Dino Esposito  

Get the sample code for this article.

DirectoryFormalizing remote tasks
How to cancel a task
In-depth understanding of the abortPostBack Method
Design uninterrupted tasks
Client code
Transactions
Generate progress bar

Last month, I built a framework to monitor ongoing server-side tasks from the client. With this framework (later called the progress monitor framework, or PMF), you can provide Web users with progress information about operations running on the server, this type of information can be obtained through a large amount of custom code. With PMF, You can have server tasks register the current status of their operations (expressed as a percentage or an estimate of the remaining time ), the client service can also Ping the server to read the status information. After the status information is downloaded to the client (out-of-band execution), it is very easy to update the user interface.

Some early feedback on last month's column pointed out two possible improvements. The first is whether PMF can be used to stop ongoing server tasks, and the second is to find a better way to generate progress bars.

Formalizing remote tasks

A remote task is a code executed on the server to respond to client events. ASP. net ajax client pages can be used to trigger remote tasks in the following three ways: the UpdatePanel control manages sending back, and directly calls a method at the backend of the application published through the Local Web service, use the PAGE method. There will soon be a fourth method: A WindowsCommunication Foundation (WCF) service.

Once a task on the server is triggered, the client no longer controls the task. The client page can be re-controlled only when the response generated by the task has been downloaded to the client and parsed. With PMF, You can dynamically read the task status, but there is no mechanism for dynamically transferring data to server tasks.

How to cancel a task

Using ASP. net ajax to cancel remote services is simple, but there are two restrictions. First, the task must have been started through UpdatePanel. Second, the server does not need any extra work to compensate for the sudden interruption of the task. Figure 1 shows the source code of the UpdatePanel-based page example. A progress template with the "cancel" button is displayed on this page, as shown in figure 2. Click this button to cancel the operation. Click?


Figure 2 Progress template with the cancel button (click the image to get a small view)
Figure 2 Progress template with the cancel button (click the image to get a larger view)

As shown in the abortTask function in 1, the Progress template contains a client button to help with JavaScript code. The primary task of this function is to retrieve the page request manager. In MicrosoftIn the AJAX client library, the PageRequestManager object is a neural hub of partial presentation. During page initialization, the page request manager registers a handler for the form submission event. In this way, the request manager is called every time the page is sent back. In this case, the request manager generates a copy of the request body according to the browser and runs the copy through the current HTTP executor (Common XMLHttpRequest object by default.

The page request manager sets partial event models and tracks ongoing operations. If any pending operation exists, the Boolean attribute isInAsyncPostBack returns true.

When you click the "cancel" button shown in figure 1, the page request manager terminates the current request through its abortPostBack method. The page request manager is an independent object, that is, all calls can only be passed to one instance. The cause of this situation is closely related to some presentation mechanisms. Partial rendering consists of sending page requests, including the general processing process on the server (excluding the rendering stage ). In addition, this means that the view status will be sent and used to recreate the last known normal state of the server control. Sending and status change events are triggered periodically. View statuses are updated based on these operations. Then, the updated view status will be sent back together with some modified labels.

Due to the relationship between view statuses, two asynchronous sending and returning calls from the same page must be serialized, and only one call can be run at a time. For this reason, the abortPostBack method on the page request manager does not need to specify which request to stop-because there is at most one pending request.

In-depth understanding of the abortPostBack Method

Let's take a brief look at the source code of the abortPostBack method in the PageRequestManager class:

function Sys$WebForms$PageRequestManager$abortPostBack(){if (!this._processingRequest && this._request){this._request.get_executor().abort();this._request = null;}}

 

If a pending request exists, the manager instructs the executor to stop the request. The executor is a JavaScript class inherited from Sys. Net. WebRequestExecutor and is responsible for sending requests and receiving responses.

In the Microsoft AJAX client library, there is only one executor class (Sys. Net. XMLHttpExecutor class) that uses the XMLHttpRequest object to execute requests. In short, when the above Code calls the abort method, it mainly informs the XMLHttpRequest object to abort. From another perspective, it only indicates that the socket used by the executor to receive response data must be closed.

Now, assume that the remote task performs destructive operations on the server. For example, you can click a button to delete a small number of records in the database table. The attempt to cancel the operation does not actually stop the server operation. All of its functions are to close the socket used to receive confirmation messages. The abortPostBack method on the PageRequestManager object is only a client method and does not play any role in operations running on the server.

Design uninterrupted tasks

To make the stop request valid for server operations, the task must be uninterrupted. In other words, the task must regularly check whether there is a description from the client indicating the task to exit. The two-way version of PMF will help you.

When I implement PMF for the first time, the framework client and server elements share a common data container. The server uses this container to write data about its progress, and the client uses this container to read the data, to update the user interface. To enable the server code to receive and process dynamic client feedback (for example, click the "cancel" button), some enhancement functions are required.

Currently, the Process Server API is based on the following conventions:

public interface IProgressMonitor{void SetStatus(int taskID, object message);string GetStatus(int taskID);bool ShouldTerminate(int taskID);void RequestTermination(int taskID);}

 

I have added two new methods: ShouldTerminate and RequestTermination. The former returns a Boolean value indicating whether the task in progress should be terminated. The RequestTermination method indicates the entry point in the API for the client that wants to end the task. When this method is called, it creates a task-related entry in the Data container (ASP. NET cache), and ShouldTerminate checks this entry to determine whether the request is interrupted.

The IProgressMonitor interface defined above indicates the expected behavior of an application on the server. You can implement this interface in different types of data containers. I created an example class using the ASP. NET cache named InMemoryProgressMonitor (see figure 3 ). Figure 4 provides a brief description of each method. As I introduced last month, the remote task repeatedly calls SetStatus to track its current execution status and mark its progress. To support dynamic interruption, ShouldTerminate will be called regularly for the same task to receive notifications when the client requests to exit. Figure 5 shows a typical structure of monitored uninterrupted tasks.

The method shown in Figure 5 is used to coordinate the steps that make up a remote task. This task can be a part of the application's intermediate layer and can be implemented as a workflow. It must be correlated between steps so that the client can insert the read status to it and the request is terminated.

Client code

The client JavaScript code used to trigger a remote task is unchanged and retains most of the content in the previous month. You can use the page or Web service method (ExecuteTask method in 5) to start a task, or run the server code in the UpdatePanel area:

<asp:UpdatePanel runat=”server” ID=”UpdatePanel1”><ContentTemplate><asp:Button runat=”server” ID=”Button1” Text=”Start Task ...”OnClick=”Button1_Click” />

 

In the button#click event handler, you define a remote task and make it call the progress monitor object and the SetStatus and ShouldTerminate methods. To suddenly terminate a remote task, you must add a "cancel" button in the Progress template. It can be an UpdateProgress control or a <div> block defined by the user. However, the click handler of the "cancel" button does not point to the abortPostBack method in the page request manager, but to your own abort method in the client progress API:

<script type=”text/javascript”>var progressManager = null;var taskID = null;function pageLoad() {progressManager = new Samples.PMF2.Progress();}function abortTask() {progressManager.abortTask(taskID);}...</script>

 

Let's take a look at the modified client progress API. This API is encoded in the progress. js file, so it must be linked to every ASP. net ajax page that is scheduled to use uninterrupted or monitoring tasks:

<asp:ScriptManager ID=”ScriptManager1” runat=”server”EnablePageMethods=”true”><Scripts><asp:ScriptReference path=”random.js” /><asp:ScriptReference path=”progress.js” /></Scripts></asp:ScriptManager>

 

The random. js file is related to progress. js and defines a method to generate a random number of tasks. To track the status of remote tasks from the client, you need to regularly poll the server. To stop a running task, or, more specifically, to send a request to stop the task, you need to call a server method, this method is released by the progress monitor Server API as part of the application backend:

// Cancel the operationfunction Samples$PMF2$Progress$abortTask() {PageMethods.TerminateTask(_taskID, null, null, null);}

 

I chose to use the PAGE method to publish this client callable function. Figure 6 provides an architecture view of the entire solution.


Figure 6 bidirectional progress monitor framework (click the image to get a smaller view)
Figure 6 bidirectional progress monitor framework (click the image to get a larger view)

When you click the "cancel" button, an out-of-band call is triggered to execute the TerminateTask method, which is defined as a page method in the subsequent code class of the page. The TerminateTask method creates a task-related entry in the internal data storage (ASP. NET cache. This entry is named after the task ID with the suffix "Quit. This entry is checked for all phases of an uninterrupted task during execution. If this entry is found, the server task is aborted (see figure 7 ).


Figure 7 the user clicks the cancel button to end the server task (click the image to get a small view)
Figure 7 the user clicks the cancel button to end the server task (click the image to get a large view)

Canceling a task in this way will be more effective. If only the client sending back is aborted during the UpdatePanel refresh process, all the results will be disabled for the client socket used to receive the response. It does not affect the code running on the server. There is no built-in method to stop remote calls to Web services or page Methods programmatically. In this case, the JavaScript proxy class completely hides the request object that is being used for pushing the call. Although the request object and its executor have a abort method, the reference to it cannot be found in the context of the Service method call.

Finally, if you need to allow remote task control, the Progress indicator mode is the only feasible method. You can set a parallel channel to monitor the status and send more information (such as exit command) to running tasks ). The same architecture allows clients to dynamically change parameters or request other operations. The bidirectional progress monitor framework is a duplex channel. Server tasks and their JavaScript clients can use this channel to exchange messages.

Transactions

So far, I have created a framework to monitor and stop ASP. NET AJAX tasks. Note that the framework only notifies the task user to request termination. If the design is correct, the task immediately stops and returns. But how can we deal with the completed work?

In general, when a task is suddenly interrupted, you should cancel all the changes it has made and return them. However, the progress monitor framework cannot implement this function. However, If You encapsulate a remote task in a transaction, you can roll it back immediately after the task is interrupted (assuming that the completed task only involves transactional resources, such as the SQL Server database ). Another option is to use a workflow. In this case, You encapsulate the task in the TransactionScope activity, use the Code activity to set the current status, and check whether there are termination requests. If the task must be terminated, an exception is thrown and transaction rollback is automatically triggered. (For more information about transactional tasks in Windows Workflow Foundation, see the "advanced technology" column in June 2007 ).

Unfortunately, not all operations can be automatically rolled back easily. Generally, you can implement tasks within the TransactionScope block and use all objects used to implement the ITransaction interface safely and effectively. If you do this, all objects will be rolled back or submitted accordingly. Each object knows how to undo its changes.

The bottom line is to monitor the progress of remote tasks from the client. This operation is relatively simple and will not have a serious negative impact. PMF adds some good abstractions and provides some ready-made programming tools. Uninterrupted tasks may cause some other problems, especially when the task has inherent transaction semantics. Writing code to notify task users to request termination is the simplest part of the game. The truly complicated part is in task implementation and compensation policies.

Generate progress bar

At the end of this article, let's take a look at how to use JavaScript to easily generate a progress bar tag and make it easier to maintain. The progress bar shown in Figure 7 is generated by creating an HTML table, as shown below:

<table width=”100%”><tr><td>69% done</td></tr><tr><td bgcolor=”blue” width=”69%”>&nbsp;</td><td width=”31%”></td></tr></table>

 

This table contains two rows: with text and meter. The meter is displayed using rows of two cells. The cell has given the background color and proportional width.

By carefully looking at the above tag, you can identify at least three parameters: user-oriented messages, values to be displayed, and colors to be used for the completed and unfinished areas. In this way, it is no longer necessary to generate string-type tags. Isn't it more concise to create JavaScript classes? The code in Figure 8 shows the main methods of the Samples. GaugeBar class.

This method uses text and percentage to return the HTML table containing two rows. The top line only displays text. The bottom line is divided into two cells with different colors.

The tag string is built using the Microsoft. NET Framework StringBuilder object of the JavaScript version. The JavaScript StringBuilder object is defined in the system namespace, and its programming interface is similar to its. NET Framework interface. Send text to the internal buffer of StringBuilder, and then use the toString method to output text.

The Samples. GaugeBar class has a generateMarkup method and attributes such as the background color of the completed and unfinished areas and the foreground color of the included text. This class is used as a singleton for performance reasons. This class is not very large, but you do not need to create a new instance for it each time you need to update the progress bar. Therefore, you have defined a static instance of this class and added some static methods and attributes:

Samples.GaugeBar.registerClass(‘Samples.GaugeBar’);Samples.GaugeBar._staticInstance = new Samples.GaugeBar();Samples.GaugeBar.generateMarkup = function(text, perc) {return Samples.GaugeBar._staticInstance.generateMarkup(text, perc);}

 

You have many methods to customize the gauge bar. To change the color, perform the following operations:

Samples.GaugeBar.set_DoneBackColor(“#ff00ee”);Samples.GaugeBar.set_TodoBackColor(“#ffccee”);

 

Similarly, you can define the border style for the "completed" cell of the table to add beautiful 3D effects, as shown below:

if (this._effect3D)builder.append(“ style=’border:outset white 2px;’”);

 

By creating a class to publish functions, You can greatly improve the manageability of JavaScript programming. If you had to handle dynamic HTML behavior a few years ago, you would understand what I mean. The Microsoft Client AJAX library is a great improvement, because it is much easier to use this library to write complex JavaScript code. Most AJAX professionals may agree that more JavaScript Functions are required to implement powerful AJAX programming.

Send your questions and comments to Dino to: cutting@microsoft.com.

NEW: getting e the sample code online!-Or-Code download location:CuttingEdge2007_08.exe (167KB)
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.