Implements ICallbackEventHandler problème

Résolu
cYoann Messages postés 6 Date d'inscription dimanche 27 novembre 2005 Statut Membre Dernière intervention 10 mars 2006 - 26 févr. 2006 à 11:34
cYoann Messages postés 6 Date d'inscription dimanche 27 novembre 2005 Statut Membre Dernière intervention 10 mars 2006 - 26 févr. 2006 à 14:51
Salut,
Voilà j'ai crée un webcontrol qui implemente l'interface ICallbackEventHandler (un bouton qui déclenche un évenement onClick sans recharger la page...)
tout fonctionne, RaiseCallbackEvent et GetCallbackResult (j'utilise asp.net 2)....
Le control fait ce que je souhaite et déclenche deux scripts (javascript)
* function OnCallBackStart (Button)
au début (quand on click dessus, en plus de WebForm_DoCallback..)
* function OnCallBackEnd (Results, Button)
à la fin

MAIS, si j'ajoute 2 boutons sur ma page et que je click sur les deux l'un après l'autre
mes deux événements OnClick sont déclenchés, tout va bien
le premier bouton qui termine sa tache déclenche OnCallBackEnd et affiche le résultat souhaité
le second bouton lui ne le déclenche pas ! et n'affiche donc pas le résultat demandé pourtant GetCallbackResult pour les 2 boutons est appelés normalement.

J'espère que je mon problème est compréhensible ! Si vous avez besoins de précisions... allez-y

Cordialement,
Yoann.
A voir également:

4 réponses

jesusonline Messages postés 6814 Date d'inscription dimanche 15 décembre 2002 Statut Membre Dernière intervention 13 octobre 2010 29
26 févr. 2006 à 14:47
Aprés relecture du code du ClientCallBack j'ai trouvé ce qui cloche.

Il faut mettre le paramètre useAsync à true

Page.ClientScript.GetCallbackEventReference(
Me, GetRequestArguments,
"OnCallBackEnd",
Me.UniqueID,
True)

En effet lorsque l'on regarde le js qui est produit par .net on retrouve :

if (!useAsync) {
if (__synchronousCallBackIndex != -1) {
__pendingCallbacks[__synchronousCallBackIndex] = null;
}
__synchronousCallBackIndex = callbackIndex;
}

est par défaut useAsync est à false ! ce qui veut dire que les requetes ajax sont annulés ! (j'ai pas vu de doc la dessus donc je vais surement blogger)

Par contre ce que je peux te conseiller c'est au lieu d'écrire le javascript directement dans la page, sert toi des webRessources pour externaliser le js :)

En tout cas ton controle à l'air trés sympathique j'ai un peu parcouru ton code et ca ressemble beaucoup à ma facon d'ecrire ;)

n'hésite pas à déposer ton controle sur ce site avec de la documentation une fois qu'il sera finit ;)


<HR>
Cyril - MVS - MCP ASP
3
jesusonline Messages postés 6814 Date d'inscription dimanche 15 décembre 2002 Statut Membre Dernière intervention 13 octobre 2010 29
26 févr. 2006 à 12:55
Si j'ai bien compris

tu essayes de faire 2 requetes ajax en meme temps ? tu cliques sur le premier, ca t'en fait une et avant que celle ci soit finit tu clicks sur le 2eme ? et ca plante :(

par contre si tu clicks sur le premier t'attend qu'il finisse puis sur le 2eme ca fonctionne ? et si tu clicks 2 fois sur le meme bouton ?

et tu pourrais nous montrer un peu de ton code / rendu ? que je voit mieux :)


<HR>
Cyril - MVS - MCP ASP
0
cYoann Messages postés 6 Date d'inscription dimanche 27 novembre 2005 Statut Membre Dernière intervention 10 mars 2006
26 févr. 2006 à 13:51
ouai c'est exactement ça,
je clic sur le premier bouton, puis sur le deuxième avant que la première requête ne soit terminée et la requête la plus lente "plante"
quand je clic sur les boutons l'un après l'autre en attendant que chaque requête se termine ça marche

si je clic deux fois sur un même boutons il n'y a aucun aucun problème !
quand je clic sur un bouton OnCallBackStart (javascript) est déclenché et mon bouton se grise :)

quand la requête se termine OnCallBackEnd (toujours du javascript) se charge de "dégriser" le bouton et d'afficher le résultat.

le code du control :
j'ai tout copier-coller dans le doute mais certaines partie ne sont peut-être pas nécessaire pour trouver le problème...

Imports System.Web.UI.WebControls
Imports System.Web.UI
Imports System.ComponentModel
Imports System.Collections.Specialize

<DefaultEvent("Click"), DefaultProperty("Text")> _
Public Class CallBackButton
Inherits WebControl
Implements ICallbackEventHandler

#Region " Déclarations privées "
Private Result As String = String.Empty
Private Result_header As String = String.Empty
Private NameOfRequestArguments As ArrayList
#End Region

Public Event Click(ByVal Args As NameValueCollection)

#Region " Utils "
Public Function RenderOtherControl(ByVal WebControl As WebControl) As String
Dim Sw As New IO.StringWriter, W As New HtmlTextWriter(Sw), R As String

WebControl.RenderControl(W)
R = Sw.ToString

W.Flush() : Sw.Flush()
W.Dispose() : Sw.Dispose()

Return R
End Function
#End Region

#Region " Properties "
Public Property Text() As String
Get
Dim Obj As Object = ViewState("Text")
If Obj Is Nothing Then Obj = Me.ID
Return CType(Obj, String)
End Get
Set(ByVal value As String)
ViewState("Text") = value
End Set
End Property
Public Property ValidationGroup() As String
Get
Dim Obj As Object = ViewState("ValidationGroup")
If Obj Is Nothing Then Obj = ""
Return CType(Obj, String)
End Get
Set(ByVal value As String)
ViewState("ValidationGroup") = value
End Set
End Property
Public Property CauseValidation() As Boolean
Get
Dim Obj As Object = ViewState("CauseValidation")
If Obj Is Nothing Then Obj = True
Return CType(Obj, Boolean)
End Get
Set(ByVal value As Boolean)
ViewState("CauseValidation") = value
End Set
End Property
Private Property RequestArguments() As ArrayList
Get
Dim Obj As Object = ViewState("RequestArguments")
If Obj Is Nothing Then Obj = New ArrayList
Return CType(Obj, ArrayList)
End Get
Set(ByVal value As ArrayList)
ViewState("RequestArguments") = value
End Set
End Property
#End Region

#Region " AddRequestArgument "
Public Sub AddRequestArgument(ByVal WebControl As WebControl, ByVal [Property] As String)
AddRequestArgument(WebControl.UniqueID.Replace("$", "_"), [Property], WebControl.ID)
End Sub
Public Sub AddRequestArgument(ByVal Id As String, ByVal [Property] As String, Optional ByVal FutureAccessName As String = "")
Dim A As ArrayList = RequestArguments
If A Is Nothing Then A = New ArrayList
A.Add("document.getElementById('" & Id & "')." & [Property])
RequestArguments = A
If NameOfRequestArguments Is Nothing Then NameOfRequestArguments = New ArrayList
NameOfRequestArguments.Add(IIf(FutureAccessName = "", Id, FutureAccessName))
End Sub
#End Region

#Region " AddResult "
Public Sub AddResult(ByVal HtmlControl As HtmlControls.HtmlGenericControl, ByVal [Property] As String, ByVal Value As String)
AddResult(HtmlControl.UniqueID.Replace("$", "_"), [Property], Value)
End Sub
Public Sub AddResult(ByVal WebControl As WebControl, ByVal [Property] As String, ByVal Value As String)
AddResult(WebControl.UniqueID.Replace("$", "_"), [Property], Value)
End Sub
Public Sub AddResult(ByVal Id As String, ByVal [Property] As String, ByVal Value As String)
Result &= Id & ":" & [Property] & ":" & Value
Result_header &= (Id & ":" & [Property] & ":" & Value).Length & ":"
End Sub
#End Region

#Region " Implémentation ICallbackEventHandler "
Private Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
If Result = "" Then Return ""
Dim R As String = Result_header.Remove(Result_header.Length - 1, 1) & " " & Result
Result = ""
Result_header = ""
Return R
End Function

Private Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
Try
Dim A As NameValueCollection = GetRequestArguments(eventArgument)
RaiseEvent Click(A)
Catch ex As Exception
Throw New Exception("Erreur (" & Me.ID & ") :
" & ex.Message)
End Try
End Sub
#End Region

#Region " Overrides OnInit "
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)

Page.ClientScript.RegisterHiddenField(Me.UniqueID & "_value", Me.Text)
'On déclare un champ caché contenant la propriété text

If Me.CauseValidation Then Page.ClientScript.RegisterClientScriptResource(GetType(BaseValidator), "WebUIValidation.js")
'On doit déclarer le script WebUIValidation.js qui contient la fonction Page_ClientValidate tant désirée :p

If Not Page.ClientScript.IsClientScriptBlockRegistered(Me.GetType, "CallBackButton") Then
Dim Script As New Text.StringBuilder

Script.AppendLine("function OnCallBackStart (Button) {")
'Script.AppendLine("alert('Start :' + Button.name);")
Script.AppendLine(" Button.disabled = true;")
Script.AppendLine(" Button.value = 'requête en cours...';")
Script.AppendLine("}")

Script.AppendLine("function OnCallBackEnd (Results, Button) {")
Script.AppendLine(" Button.disabled = false;")
Script.AppendLine(" Button.value = document.getElementById(Button.name + '_value').value;")
Script.AppendLine(" var header = Results.substr(0,Results.indexOf(' ')).split(':');")
Script.AppendLine(" cPosition = Results.indexOf(' ') + 1;")
Script.AppendLine(" for (var i = 0; i < header.length; i++) {")
Script.AppendLine(" var item = Results.substr(cPosition, header[i]);")
Script.AppendLine(" var id = item.split(':')[0];")
Script.AppendLine(" var property = item.split(':')[1];")
Script.AppendLine(" var value = item.substr(id.length + property.length + 2, header[i] - id.length - property.length - 2);")
Script.AppendLine(" document.getElementById(id)[property] = value;")
Script.AppendLine(" cPosition += Math.round(header[i]);")
Script.AppendLine(" }")
Script.AppendLine("}")

Script.AppendLine("function GetArgs(Args) {")
Script.AppendLine(" var header = '';")
Script.AppendLine(" for (var i = 0 ; i < Args.length ; i ++) {")
Script.AppendLine(" header += ' ';")
Script.AppendLine(" if (typeof(Args[i]) != 'number') {")
Script.AppendLine(" var subArgs = Args[i].split('\n');")
Script.AppendLine(" for (var j = 0 ; j < subArgs.length ; j ++) {")
Script.AppendLine(" header += subArgs[j].length;")
Script.AppendLine(" if (j < subArgs.length - 1) header += ':';")
Script.AppendLine(" }")
Script.AppendLine(" } else {")
Script.AppendLine(" Args[i] += '';")
Script.AppendLine(" header += Args[i].length;")
Script.AppendLine(" }")
Script.AppendLine(" }")
Script.AppendLine(" return (new Array(header, Args));")
Script.AppendLine("}")

Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "CallBackButton", Script.ToString, True)
End If
End Sub
#End Region

#Region " GetRequestArguments "
'Encodage javascript
Private Function GetRequestArguments() As String
If RequestArguments.Count = 0 Then Return String.Empty
Dim Args As String = "GetArgs(new Array("
For i As Integer = 0 To RequestArguments.Count - 1
Args &= RequestArguments(i)
'If i <> RequestArguments.Count - 1 Then Args &= ", "
Args &= ","
Next
Return Args & "''))"
End Function

'Décodage javascript
Private Function GetRequestArguments(ByVal Value As String) As NameValueCollection
Dim Args As New NameValueCollection
If Value = "" Then Return Args
Dim Header As String = Value.Substring(0, Value.IndexOf(",")).Trim(" ")

Dim CurrentPosition As Integer = Header.Length + 2
Dim i As Integer = 0
For Each ArgLength As String In Header.Split(" ")
Dim Arg As String = ""
For Each SubArgLength As String In ArgLength.Split(":")
Arg &= Value.Substring(CurrentPosition, SubArgLength) & vbCrLf
CurrentPosition += SubArgLength + 1
Next
If i < NameOfRequestArguments.Count Then Args.Add(NameOfRequestArguments(i), Arg.Remove(Arg.Length - vbCrLf.Length, vbCrLf.Length))
i += 1
Next

Return Args
End Function
#End Region

#Region " Render "
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim ValidationScript As String = IIf(Me.CauseValidation, "if(!Page_ClientValidate('" & Me.ValidationGroup.ToString & "')) return; ", "")

Dim Button As New HtmlControls.HtmlInputButton
Button.ID = Me.UniqueID
Button.Value = Me.Text
Button.Attributes.Add("onclick", "javascript:" & ValidationScript & "OnCallBackStart(this);" & Page.ClientScript.GetCallbackEventReference(Me, GetRequestArguments, "OnCallBackEnd", Me.UniqueID) & ";")
'Button.Attributes.Add("onclick", "javascript:" & ValidationScript & "OnCallBackStart(this);" & Page.ClientScript.GetCallbackEventReference(Me, GetRequestArguments, "OnCallBackEnd_" & Me.UniqueID, Me.UniqueID) & ";")
Button.Attributes.Add("class", Me.CssClass)
Button.RenderControl(writer)
End Sub
#End Region

End Class

un peut lourd ?!
la région AddRequestArgument, permet juste de récupérer des variables pour l'événement Click (par exemple le texte contenu dans un textbox...)
la région AddResult quand à elle sert à retourner le/les résultats (par exemple 'b1 terminé' à écrire dans une div...)

ma page qui permêt de tester "le bug" :

<cc1:CallBackButton Text="button 1" ID="b1" runat="server" />
<cc1:CallBackButton Text="button 2" ID="b2" runat="server" />

et son code :
Protected Sub b1_Click(ByVal Args As System.Collections.Specialized.NameValueCollection) Handles b1.Click
Dim o As Integer = 0
For i As Integer = 0 To 500000000
o += 1
Next
b1.AddResult("state", "innerHTML", "b1 terminé")
End Sub

Protected Sub b2_Click(ByVal Args As System.Collections.Specialized.NameValueCollection) Handles b2.Click
Dim o As Integer = 0
For i As Integer = 0 To 2000000
o += 1
Next
b2.AddResult("state", "innerHTML", "b2 terminé")
End Sub

voili,
jespère que ça va t'aider.
0
cYoann Messages postés 6 Date d'inscription dimanche 27 novembre 2005 Statut Membre Dernière intervention 10 mars 2006
26 févr. 2006 à 14:51
merci !
pour la réponse et les conseils
0
Rejoignez-nous