有啥方法可以进行同步 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 和 AJAX 调用将 JQuery 脚本错误记录到 ASP.NET 服务器
将Javascript PageMethods“返回值”存储到变量中