Any way to do a synchronous PageMethods call?
Asked Answered
B

5

7

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.

Bevins answered 14/7, 2011 at 21:45 Comment(0)
H
12

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.

Haye answered 14/7, 2011 at 21:47 Comment(0)
P
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;
}
Peskoff answered 24/4, 2012 at 20:46 Comment(0)
W
1

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];
Worrywart answered 10/10, 2013 at 22:7 Comment(1)
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.Worrywart
S
1

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.

Saturninasaturnine answered 12/2, 2014 at 22:54 Comment(0)
D
1

I wrote this, that lets you call a PageMethod synchronously. It also will just return the result of the method, and throw an error that can be caught in a try/catch block, so you don't need to worry about supplying onSuccess and onError functions.

function synchronusPageMethod(method) {

    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);

        return this.original_open.apply(this, eventArgs);
    };

    var result;
    var error;

    var args = Array.prototype.slice.call(arguments).slice(1);
    args.push(function (res) {
        result = res;
    });

    args.push(function (err) {
        error = err;
    });

    method.apply(null, args);

    XMLHttpRequest.prototype.open = XMLHttpRequest.prototype.original_open;

    if (error !== undefined) {
        throw error;
    } else {
        return result;
    }
}

Use it like this:

try {
    var result = synchronusPageMethod(PageMethods.myMethod, argument0, argument1);
    console.log(result);
} catch(error) {
    console.log(error);
}
Dowski answered 18/10, 2018 at 21:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.