有啥方法可以进行同步 PageMethods 调用?

Posted

技术标签:

【中文标题】有啥方法可以进行同步 PageMethods 调用?【英文标题】:Any way to do a synchronous PageMethods call?有什么方法可以进行同步 PageMethods 调用? 【发布时间】:2011-10-05 17:32:33 【问题描述】:

我正在尝试这样做:

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

但它仍然异步运行。我需要浏览器真正等到我的代码隐藏执行完毕,然后才能刷新它

有一个列表框加载了刚刚从数据库中删除的值,它们不应该是可见的。我遇到的问题是窗口位置在执行代码隐藏之前刷新,并且似乎没有任何内容被用户删除。

【问题讨论】:

【参考方案1】:

改为使用 jQuery ajax 调用它?它具有一个选项 (async),您可以在其中选择同步/异步模式:http://api.jquery.com/jQuery.ajax/

这篇优秀的文章告诉你如何最好地从 jQuery 调用 PageMethods:http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/

基本上,您需要做的就是:

$.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";
  
);

查看Crockford's JSON stringify 获取 json 格式化解决方案。

【讨论】:

【参考方案2】:

如果您想避免使用 jQuery,一个变通方法是使用另一个 PageMethod,您可以在其中使用 javascript setInterval 函数检查操作的状态。它有点乱,但如果你想要零 jQuery,它就可以完成工作,它模仿你寻求的同步性。我将它用于大型操作,其中我想将进度条更新到客户端或其他东西。以下是根据您发布的代码如何执行此操作的示例:

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;
        

代码隐藏:

[WebMethod]
public static string CheckDeleteBatchStatus()

    string status = GetDeleteBatchStatus(); //some function to get the status of your operation
    return status;

【讨论】:

【参考方案3】:

我偶然发现了这个网站:

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

它有一个很好的方法来处理同步 PageMethod 调用。

javascript代码如下:

// 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];

【讨论】:

我想到如果它能够处理 WebMethodCall 函数的任意参数会更好,但我还不知道该怎么做。【参考方案4】:

Using jQuery 在 2009 年是 first recommended。

另一个(非常冗长)选项是实现一个同步 WebRequestExecutor,如 here (2007-07-04) 所示,并完善了 here (2007-10-30)。该技术的要点是将 ASP.NET AJAX Sys.Net.XMLHttpExecutor 复制为名为 Sys.Net.XMLHttpSyncExecutor 的新类,并将调用更改为 xmlHttpRequest.open 以将 false 作为最后一个参数传递以强制同步操作。

可以使用WebRequestManager 将同步执行器插入到所有请求中,如下所示:

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

或者您可能希望根据请求切换它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 是这些链接中的大部分以及其他一些链接的来源。

【讨论】:

【参考方案5】:

我写了这个,它可以让你同步调用一个 PageMethod。它也只会返回方法的结果,并抛出可以在 try/catch 块中捕获的错误,因此您无需担心提供 onSuccess 和 onError 函数。

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;
    

像这样使用它:

try 
    var result = synchronusPageMethod(PageMethods.myMethod, argument0, argument1);
    console.log(result);
 catch(error) 
    console.log(error);

【讨论】:

以上是关于有啥方法可以进行同步 PageMethods 调用?的主要内容,如果未能解决你的问题,请参考以下文章

PageMethods 和 UpdatePanel

通过 PageMethods 和 AJAX 调用将 JQuery 脚本错误记录到 ASP.NET 服务器

将Javascript PageMethods“返回值”存储到变量中

来自 javascript PageMethods 的自定义 C# 数据传输对象

有啥方法可以进行“一劳永逸”的 API 调用?

有啥方法可以保护在开源项目中进行的 Web 服务调用? [关闭]