[SPRN05976]【Ajax】SPREADでコールバックを発生させるとSystem.Web.UI.ICallbackEventHandlerを使用したページのコールバックが動作しなくなる

文書番号 : 23289     文書種別 : 制限事項     最終更新日 : 2006/12/27
文書を印刷する
対象製品
SPREAD for .NET 2.5J Web Forms Edition
発生環境
Visual Studio 2005
ASP.NET 2.0
詳細
SPREADでコールバックを発生させるとSystem.Web.UI.ICallbackEventHandlerを使用したページのコールバックが動作しなくなります。

この動作はASP.NETにおけるイベントデータの検証がViewStateの値を対象としていることに起因します。

SPREADのコールバックではViewStateの内容を更新します。ASP.NETのイベントデータの検証はViewStateの値を元に行われますので、SPREADのコールバックによって更新されたViewStateの内容が検証違反となってしまいます。この動作は製品実装上の制限事項です。

下記、この現象の再現手順です。

[再現手順]
(1)WebフォームにSPREAD, TextBox, HTML Button 2個を配置します。

 Button1: ASP.NET のICallbackEventHandlerでコールバックし
      サーバー側で取得した現在時刻をフォーム上に表示します。
      Button1のHTMLソースを次の様に設定します。

     <input id="Button1" style="position: static" type="button" value="page.callback" onclick="doCallBack();"/>

 Button2: SPREADでコールバックし、シートの背景色を変更します。
      Button2のHTMLソースを次の様に設定します。

     <input id="Button2" style="position: static" type="button" value="spread.callback" onclick="doFpCallBack();"/>

(2)ICallbackEventHandlerによるコールバックの結果を表示するために下記<SPAN>を追加します。
 
     <span id="result" style="background-color:beige">result:</span>

(3)下記のコードとクライアント側スクリプトを追加します。

------------------------------------------
WebForm1.aspx.vb
------------------------------------------
Partial Class Default
  Inherits System.Web.UI.Page
  Implements System.Web.UI.ICallbackEventHandler
  
  Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
    'コールバックレスポンスの設定
    Dim result As String
    result = DateTime.Now.ToLongTimeString
    Return result
  End Function

  Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
    'コールバックリクエストの取得
  End Sub

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    'コールバックイベントの登録
    Dim cbReference As String = Page.ClientScript.GetCallbackEventReference(Me, "arg", "receiveServerData", "context", "clientErrorCallback", False)
    Dim callbackScript As String = "function CallServer(arg, context, clientError,isAsync) { " & cbReference & "} ;"
    Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallServer", callbackScript, True)

    'Me.EnableViewStateMac = False
  End Sub

  Protected Sub FpSpread1_ButtonCommand(ByVal sender As Object, ByVal e As FarPoint.Web.Spread.SpreadCommandEventArgs) Handles FpSpread1.ButtonCommand
    'コールバックでシート背景色を変更する
    If e.CommandName = "mycommand" Then
      If e.SheetView.BackColor.Equals(System.Drawing.Color.Beige) Then
        e.SheetView.BackColor = Drawing.Color.WhiteSmoke
      Else
        e.SheetView.BackColor = Drawing.Color.Beige
      End If
    End If
  End Sub
End Class

---------------------------------------------
WebForm1.aspx
---------------------------------------------
  <script type="text/javascript">
    function doFpCallBack(){
      var s=document.getElementById("FpSpread1");
      s.CallBack("mycommand");//コールバック      
    }
    function doCallBack(){
      CallServer("","",clientErrorCallback,false);      
    }
    function clientErrorCallback(arg,context){
      alert(arg);
    }    
    function receiveServerData(arg,context){
      result.innerText=arg;
    }
  </script>

(4)実行します。

(5)Button1("page.callback")を複数回クリックします。
  --- コールバックが発生し、表示時刻が更新されます。
(6)Button2("spread.callback")を複数回クリックします。
  --- SPREADのコールバックが発生し、シート色が変更されます。
(7)Button1をクリックします。
  --- コールバックが発生せず、時刻は更新されません。
回避方法
次のいずれかの方法で回避できます。

●方法1●
ページのEnableEventValidationをFalseに設定します。

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="TextBox.aspx.vb" Inherits="Default28" EnableEventValidation="false"%>

●方法2●
ページおよびSPREADのコールバックの際にそれぞれ「__EVENTVALIDATION」の値を設定します。

<script type="text/javascript">
    var pageValidation = null;
    var spreadValidation = null;
    
    function initSpread() {
      var txt = document.getElementById("__EVENTVALIDATION");
      
      if (txt!=null) {
        pageValidation = spreadValidation = txt.value;   
      }
    }
    
    function doFpCallBack(){
      var txt = document.getElementById("__EVENTVALIDATION");
      if (txt!=null) {
        txt.value = spreadValidation;
      }
      
      var s=document.getElementById("FpSpread1");
      s.CallBack("mycommand");//コールバック 
      
      if (txt!=null) {        
        spreadValidation = txt.value;
      }
    }
    function doCallBack(){
      var txt = document.getElementById("__EVENTVALIDATION");
      if (txt!=null) {               
        txt.value = pageValidation;
      }
      CallServer("","",clientErrorCallback,false); 
    }
    function clientErrorCallback(arg,context){
      alert(arg);
      var txt = document.getElementById("__EVENTVALIDATION");
      if (txt!=null) {
        txt.value = spreadValidation;
      }
    }    
    function receiveServerData(arg,context){
      result.innerText=arg;
      
      var txt = document.getElementById("__EVENTVALIDATION");
      if (txt!=null) {
        txt.value = spreadValidation;
      }
    }
  </script>

<body onload="initSpread();">

この文書は、以前は次のFAQ IDで公開されていました : 6745