ASP.NET 2.0 Client Callback 的一些问题

1。http://social.msdn.microsoft.com/Forums/en-US/netfxjscript/thread/6c4db554-539a-4b5e-9c0c-e1c41eed4fbb/

Async Calls using ASP.NET 2.0 Client Callback won't work properly if the OnComplete function makes another Client Callback

Ref: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=270828&SiteID=1

If you make an asynchronous callback using ASP.NET 2.0 client callback and the OnComplete function you defined makes another callback then you will exeperience unwanted behavior. Here is how it gets started...

[code lang="javascript"]

Code Snippet

function StartFirstCallback() {
   // execute first callback. you get this script from Page.ClientScript.GetCallbackEventReference
   WebForm_DoCallback('__Page', "", OnFirstCallbackComplete, null, null, true);
}

function OntFirstCallbackComplete(result, context) {
  alert("First Callback Complete");
  
// execute second callback. you get this script from Page.ClientScript.GetCallbackEventReference
   WebForm_DoCallback('__Page', "", OnSecondCallbackComplete, null, null, true);
}

function OnSecondCallbackComplete(result, context) {
  alert("Second Callback Complete");
}

 

[/code]

When you execute the StartFirstCallback function, you will see many alert winows showing "First Callback Complete" and "Second Callback Complete" messages. The reason for this lies in a minor bug in "WebForm_CallbackComplete" function of inbuilt ASP.NET function. Here is the function extracted using Reflector:

[code lang="javascript"]

Code Snippet
function WebForm_CallbackComplete() {
    for (i = 0; i < __pendingCallbacks.length; i++) {
        callbackObject = __pendingCallbacks[ i ];
        if (callbackObject && callbackObject.xmlRequest && (callbackObject.xmlRequest.readyState == 4)) {
            WebForm_ExecuteCallback(callbackObject);
            if (!__pendingCallbacks[ i ].async) {
                __synchronousCallBackIndex = -1;
            }
            __pendingCallbacks[ i ] = null;
            var callbackFrameID = "__CALLBACKFRAME" + i;
            var xmlRequestFrame = document.getElementById(callbackFrameID);
            if (xmlRequestFrame) {
                xmlRequestFrame.parentNode.removeChild(xmlRequestFrame);
            }
        }
    }
}

 

[/code]

 

The bug is due to the point at which the WebForm_ExecuteCallback function gets invoked. This function is responsible to invoke the OnComplete function. But the "__pendingCallbacks" "global" array is updated only after executing the OnComplete function. Note that "__pendingCallbacks" global array is also used inside "WebForm_DoCallback" function to add new requests. The following piece of code is extracted from WebForm_DoCallback function:

[code lang="javascript"]

Code Snippet
function WebForm_DoCallback(...) {
 ...
 ...
    var callback = new Object();
    callback.eventCallback = eventCallback;
    callback.context = context;
    callback.errorCallback = errorCallback;
    callback.async = useAsync;
    var callbackIndex = WebForm_FillFirstAvailableSlot(__pendingCallbacks, callback);
 ...
 ...
}

 

 

[/code]

[/code]

 

Here is what happens when the StartFirstCallback function is invoked for the first time:

1. WebForm_DoCallback is called
2. __pendingCallbacks is updated by adding this new request (from step 1). __pendingCallbacks.length = 1
3. Callback completes and WebForm_CallbackComplete is called.
4. [inside WebForm_CallbackComplete]: walks the __pendingCallbacks array (which has one element) and executes the OnComplete function viz. OnFirstCallbackComplete.
5. [inside OnFirstCallbackComplete]: "First Callback Complete" message is shown. Another async callback requested (OnComplete = OnSecondCallbackComplete)
5.1 [inside WebForm_DoCallback]: __pendingCallbacks is updated by adding this new request (from step 1). __pendingCallbacks.length = 2.

Now by the time __pendingCallbacks array is updated inside WebForm_CallbackComplete function at step 4, the async operation completes so quickly that WebForm_CallbackComplete is invoked again for second call (made at Step 5). Here the __pendingCallbacks has 2 elements and most importantly the 0th element is still available (because "__pendingCallbacks[ i ] = null" statement is still not executed for the very first call) which means the OnStartFirstCallbackComplete function is called again. This starts a kind of infinite calls and only delayed response can stop this.

FIX:
Fixing this requires just moving the WebForm_ExecuteCallback statement as the last statement in WebForm_CallbackComplete routine. This ensures that __pendingCallbacks global array is updated before the OnComplete function gets invoked. Here is the updated version.

[code lang="javascript"]

Code Snippet
function
WebForm_CallbackComplete_SyncFixed() {
  // SyncFix: the original version uses "i" as global thereby resulting in javascript errors when "i" is used elsewhere in consuming pages
  for (var i = 0; i < __pendingCallbacks.length; i++) {
   callbackObject = __pendingCallbacks[ i ];
  if (callbackObject && callbackObject.xmlRequest && (callbackObject.xmlRequest.readyState == 4)) {
   // the callback should be executed after releasing all resources
   // associated with this request.
   // Originally if the callback gets executed here and the callback
   // routine makes another ASP.NET ajax request then the pending slots and
   // pending callbacks array gets messed up since the slot is not released
   // before the next ASP.NET request comes.
   // FIX: This statement has been moved below
   // WebForm_ExecuteCallback(callbackObject);
   if (!__pendingCallbacks[ i ].async) {
     __synchronousCallBackIndex = -1;
   }
   __pendingCallbacks[i] = null;

   var callbackFrameID = "__CALLBACKFRAME" + i;
   var xmlRequestFrame = document.getElementById(callbackFrameID);
   if (xmlRequestFrame) {
     xmlRequestFrame.parentNode.removeChild(xmlRequestFrame);
   }

   // SyncFix: the following statement has been moved down from above;
   WebForm_ExecuteCallback(callbackObject);
  }
 }
}

 

 

[/code]

 

Lastly, in order to make sure this function is called instead of original version, the following statement should be executed as startup script.

[code lang="javascript"]

Code Snippet
if (typeof (WebForm_CallbackComplete) == "function") {
  // set the original version with fixed version
  WebForm_CallbackComplete = WebForm_CallbackComplete_SyncFixed;
}

 

 

[/code]

 

[/code]

 

[/code]

[/code]

2.http://forums.asp.net/p/934338/1141715.aspx#1141715

Client CallBack doesn't support sync operations

GetCallbackEventReference overloaded with this signature:

public function GetCallbackEventReference (
    control : Control,
    argument : String,
    clientCallback : String,
    context : String,
    useAsync : boolean
) : String

But when I try to use callback syncroniously it's still act async way.
To clarify what I have just said little code snippet:

put an html button on web form make it server-side control.
When in page_load write:
Button1.Attributes["onclick"] = ClientScript.GetCallbackEventReference(this, "", "callback", null, false) + ";alert(xxx);";

at client-side the code is as following:

 

<script language=javascript>

 

 

 

 

 

 

var

xxx;

 

 

 

function

callback(response, context)

{

xxx =

 

"I should see this message"

;

}

 

 

</script>

So, if I pass useAsync = false alert(xxx) should happens after callback event.
But it's not.
If you run this code you'l see alert "undefine
d".

------------------------------

I'm having the same problem. The reason to occur that thing is that the function WebForm_DoCallback(Javascript function generated by the Framework) have the following line of code:

xmlRequest.open("POST", theForm.action, true);

To do a Syncronous call the third parameter have to be false.

Anyone know if the Microsoft Framework has any function to create a function with a xmlRequest syncronous? Like:

xmlRequest.open("POST", theForm.action, false);

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值