- PR -

ASP.NET CustomValidator と XMLウェブサービス(非同期)の組み合わせ

投稿者投稿内容
K
会議室デビュー日: 2008/05/16
投稿数: 6
投稿日時: 2008-05-16 20:38
はじめまして。
最近C#での開発を始めた者です。

asp:CustomValidator(およびajaxToolkit:ValidatorCalloutExtender)と
XMLウェブサービス(非同期)を組み合わせて、下記のようなことがしたいのですが、
どうもうまく動きません。
お知恵をお貸しいただければ幸いです。

開発環境
・VisualStudio.NET 2005
・C#
・ASP.NET Ajax Control Toolkit(Version 1.0.20229)

やりたい事

・CustomValidatorを用い、TextBoxに対してチェック処理を行う。
・チェックの内容はCustomValidatorのClientValidationFunctionからコールした
 XMLウェブサービス(非同期)を用いたDBとの重複チェック処理。
・チェックの結果により重複エラーとし、CustomValidatorを通じ
 ValidatorCalloutExtenderへ出力

いかにソースの抜粋を記します(適宜改行しています)。

クライアントサイド:test.aspx
-----------------------------------------------------------------------
<asp:TextBox ID="uid" runat="server" MaxLength="20"
width="150px"></asp:TextBox>
<asp:CustomValidator ID="cv" runat="server"
ControlToValidate="uid"
ClientValidationFunction="id_Validate"
Display="Dynamic"
ErrorMessage="入力されたユーザIDは既に使用されています。">!重複エラー</asp:CustomValidator>
<ajaxToolkit:ValidatorCalloutExtender ID="vce"
runat="server"
TargetControlID="cv">
</ajaxToolkit:ValidatorCalloutExtender>
<script language="javascript" type="text/javascript">
<!--
var blnSuccess;
function id_Validate(sender, e) {
blnSuccess = true;
if($get('<%=uid.ClientID%>').value!=''){
myNameSpace.WebService.ServiceBridge.uidChk(
$get('<%=uid.ClientID%>').value,
OnSuccess,
OnFailure
);
}
//なぜかここにalertを挟むと正常に動作します。
//myNameSpace.WebService.ServiceBridge.uidChkを用いたXML非同期通信
//を終えていないのに以下の処理を実行している?
//alert(blnSuccess);
e.IsValid = blnSuccess;
}
function OnSuccess(result,cx,name){
blnSuccess = result;
}
function OnFailure(ext,cs,name, e){
//XML非同期通信失敗時は常にtrue
blnSuccess = true;
}
-->
</script>
-----------------------------------------------------------------------
サーバサイド:webservice.asmx.cs(コードビハインドしています)
-----------------------------------------------------------------------
using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
using System.Text;
namespace myNameSpace.WebService
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class ServiceBridge : System.Web.Services.WebService
{
[WebMethod]
public Boolean uidChk(String uid)
{
//割合します。
//DBへの存在チェックを行い、結果をブール値で
//返しています。
Boolean ret = false;
return ret;
}
}
}
-----------------------------------------------------------------------

xmlHttpのステータスをチェックし、XML非同期通信完了なら e.IsValidへの値の
セットを行うようにすればいけそうなのですが、ajaxToolkitを用いているため
XML非同期通信に絡む部分は自動生成のため、手が出せません。

どうか、お知恵をお貸しください。

以上、よろしくお願いいたします。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2008-05-16 22:11
引用:
//なぜかここにalertを挟むと正常に動作します。
//myNameSpace.WebService.ServiceBridge.uidChkを用いたXML非同期通信
//を終えていないのに以下の処理を実行している?

非同期なのでこれで正しい動きなんだと思います。WebサービスでThread.Sleepとか
してみると、alertをはさんでも同様の現象が起こりうる事が確認できます。

[ メッセージ編集済み 編集者: べる 編集日時 2008-05-16 23:22 ]
Access
ぬし
会議室デビュー日: 2002/04/08
投稿数: 829
投稿日時: 2008-05-17 06:59
CustomValidatorでWebサービスを利用するには非同期ではなく、同期モードで呼ばないといけないのでは?

たとえば、[送信]ボタンをクリックしたときに、CustomValidatorの検証処理が実行されますが、このときCustomValidatorから非同期でWebサービスをリクエストするとtrueで戻りますよね。OnSuccess()へは、Webサービスが完了した時点で渡りますから遅すぎます。

Webサービスを同期型でリクエストするか、UpdatePanelを使用して部分更新してはどうでしょうか。

コード:
var blnSuccess; 
function id_Validate(sender, e) { 
  blnSuccess = true; 
  if($get('<%=uid.ClientID%>').value!=''){ 
    myNameSpace.WebService.ServiceBridge.uidChk( 
      $get('<%=uid.ClientID%>').value, 
      OnSuccess, 
      OnFailure 
    ); 
  }
}


_________________
ASP.NET+Ajaxサンプル集 | JavaScript+Ajaxサンプル集
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2008-05-17 14:43
UpdatePanelを利用するやりかたを考えてみました。

そもそも、CustomValidatorにはもともとサーバ側で検証する機能があるわけで
それを利用するのが正攻法でしょうね。

aspx
引用:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" OnTextChanged="TextBox1_TextChanged"></asp:TextBox>&nbsp;
<cc1:validatorcalloutextender id="ValidatorCalloutExtender1" runat="server" targetcontrolid="CustomValidator1"></cc1:validatorcalloutextender>
<asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="TextBox1"
Display="None" ErrorMessage="エラー" OnServerValidate="CustomValidator1_ServerValidate"
ValidateEmptyText="True"></asp:CustomValidator>
</ContentTemplate>
</asp:UpdatePanel>



c#
コード:
protected void TextBox1_TextChanged(object sender, EventArgs e)
    {
        //AutoPostBack="True"の動きでポストバックされた場合
        //CustomValidator1_ServerValidateを通らないのでこうしています。
        Validate();
    }
    protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
    {
        if (判定)
        {
            args.IsValid = true;
        }
        else args.IsValid = false;
    }



CustomValidatorのEnableClientScriptをfalseにするとajax側でエラーになっちゃいます。

というか、ここをみると「ちなみに、ValidatorCalloutコントロールは(執筆時点で)サーバに
対するポストバックを経た後にはバルーンを自動的に表示しない。」とあるので
サポートされた動きではないのかもしれません。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-05-17 21:56
ご希望の動作は、一見便利そうです。

では、こうなったらどうしましょう?

あ:「データ」を登録しようとしている。
  →問い合わせたところ、データはなかった。
い:「データ」を登録しようとしている。
  →問い合わせたところ、データはなかった。
  →登録した。
あ:登録した。
  →"い"が登録したデータと、重複してしまう。
Access
ぬし
会議室デビュー日: 2002/04/08
投稿数: 829
投稿日時: 2008-05-18 07:19
引用:

ご希望の動作は、一見便利そうです。
では、こうなったらどうしましょう?


重複のエラーは、タイミングの問題がありますから検証コントロールで100%チェックできませんよね!

つまり、検証時にOKになってもタイミングによってはデーベースに登録時にエラーになる。

この辺の問題は、仕様を明確にすれば問題ないかと。

_________________
ASP.NET+Ajaxサンプル集 | JavaScript+Ajaxサンプル集

[ メッセージ編集済み 編集者: Access 編集日時 2008-05-18 07:20 ]
Access
ぬし
会議室デビュー日: 2002/04/08
投稿数: 829
投稿日時: 2008-05-18 17:23
同期型のWebリクエストを行うCustomValidatorのサンプルです。
よろしければ参考にしてください。

AjaxCustomValidatorのライブデモ
http://asp35.com/samples/080518VB-3.aspx?it=demo

XMLHttpSyncExecutor.js は
http://geekswithblogs.net/rashid/archive/2007/07/04/SJAX-Call.aspx
に掲載されています。
_________________
ASP.NET+Ajaxサンプル集 | JavaScript+Ajaxサンプル集
K
会議室デビュー日: 2008/05/16
投稿数: 6
投稿日時: 2008-05-19 10:18
多数の書き込みありがとうございます。

どうも同期/非同期の概念を正しく理解していなかったことが原因のようです。
勉強不足でした。
いろいろと試してみた結果、コーディングの簡便性を考慮するとべるさんの
UpdatePanelを利用したやり方のほうがよさそうでした。
ValidatorCalloutExtenderのバルーン表示も正常に動作しました。
ありがとうございました。

引用:
-------------------------------------------------------------------------------
ご希望の動作は、一見便利そうです。
では、こうなったらどうしましょう?
-------------------------------------------------------------------------------

登録処理実行直前にもう一度チェックを行うつもりでした。

引用:
-------------------------------------------------------------------------------
同期型のWebリクエストを行うCustomValidatorのサンプルです。
よろしければ参考にしてください。
-------------------------------------------------------------------------------

こういうやり方もあるのですね。
参考になりました。

大変助かりました。
ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)