Any way to do a synchronous PageMethods call?

16,385

Solution 1

Call it using jQuery ajax instead? It features an option (async) where you can select sync/async mode: http://api.jquery.com/jQuery.ajax/

This excellent article tells you how best to call PageMethods from jQuery: http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/

Essentially, all you will need to do is this:

$.ajax({
  type: "POST",
  async: false,
  url: "yourpage.aspx/DeleteBatchJSWM",
  data: "{ put json representation of userInfo here }",
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  success: function(msg) {
    window.location = "BatchOperations.aspx";
  }
});

Look at Crockford's JSON stringify for a json formatting solution.

Solution 2

If you want to avoid using jQuery, a work around would be to use another PageMethod in which you check the status of the operation using the javascript setInterval function. It is a little messy, but it does the job if you want zero jQuery and it mimics the synchronicity you seek. I use it for large operations in which I want to update a progress bar to the client or something. Here would be an example of how you would do this given what code you posted:

function DelBatch()
{

        var userInfo = get_cookie("UserInfo");
        PageMethods.DeleteBatchJSWM(userInfo, function(result) {window.location = "BatchOperations.aspx";});

        var status;

    //Check to see if it has completed every second
        var myInterval = setInterval(function ()
        {
            PageMethods.CheckDeleteBatchStatus(OnSuccess);
                if (status == "Finished")
                {
                    clearInterval(myInterval);
                        //Finished Deleting. Call your window refresh here
                WindowRefresh(); 
                }
        }, 1000);


        function OnSuccess(result)
        {
            status = result;
        }
}

Code Behind:

[WebMethod]
public static string CheckDeleteBatchStatus()
{
    string status = GetDeleteBatchStatus(); //some function to get the status of your operation
    return status;
}

Solution 3

I came across this site:

http://abhijit-j-shetty.blogspot.com/2011/04/aspnet-ajax-calling-pagemethods.html

that had a great method for handling Synchronous PageMethod calls.

The javascript code is as follows:

// Make sure page methods operate synchronously
XMLHttpRequest.prototype.original_open = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function (method, url, async, user, password) {

    async = false;

    var eventArgs = Array.prototype.slice.call(arguments);

    var q = 0;
    return this.original_open.apply(this, eventArgs);
}

// Make a generic WebMethod caller:
function WebMethodCall(FunctionName, callingobj) {
    var OnSuccess = function (result, userContext, methodName) {
        callingobj.push(result);
    }

    var OnFailure = function (error, userContext, methodName) {
        callingobj.push(error.get_message());
    }

    PageMethods[FunctionName](OnSuccess, OnFailure);

}

// OK, this is kludgy, but here goes. In order to have a synchronous PageMethod call
// we need an object that persists in the namespace to stuff the result value into (like an array)
// Essentially I'm emulating a ByRef call.

// ThisResult is an empty list. The WebMethodCall function sticks a value into that list.
// The code that makes the PageMethods get called synchronously is in Common.js

// Use the functions
var ThisResult = []; // This must be of a type which persists in the namespace
WebMethodCall('HelloWorld', ThisResult);
return ThisResult[0];

Solution 4

Using jQuery was first recommended back in 2009.

Another (extremely verbose) option is implementing a synchronous WebRequestExecutor as shown here (2007-07-04), and perfected here (2007-10-30). The gist of the technique is to copy the ASP.NET AJAX Sys.Net.XMLHttpExecutor as a new class named Sys.Net.XMLHttpSyncExecutor and change the call to xmlHttpRequest.open to pass false as the last parameter to force synchronous operation.

The synchronous executor can be plugged into all requests using WebRequestManager like this:

Sys.Net.WebRequestManager.set_defaultExecutorType('Sys.Net.XMLHttpSyncExecutor');

or you may want to switch it up per-request just before it is invoked:

Sys.Net.WebRequestManager.add_invokingRequest(function(sender, args) {
 if (iFeelLikeRunningThisRequestSynchronously) {
  args.get_webRequest().set_executor(new Sys.Net.XMLHttpSyncExecutor());
}});

This discussion is the source for most of these links and a few more.

Share:
16,385
Admin
Author by

Admin

Updated on June 16, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to do this:

    function DelBatch()
    {var userInfo = get_cookie("UserInfo");
    PageMethods.DeleteBatchJSWM(userInfo, function(result)
                                              {window.location = "BatchOperations.aspx";});
    }
    

    But it still runs asynchronously. I need the browser to actually wait until my code-behind is finished executing, then it can be refreshed

    There's a listbox loaded with values that were just deleted from the database, they shouldn't be visible. Problem I have is the window location refreshes before the code-behind is executed, and nothing seems like it was deleted to the user.

  • nickvans
    nickvans over 10 years
    It occurs to me that this would be better if it were able to handle arbitrary arguments to the WebMethodCall function, but I don't know how to do that yet.