検索 
2010年9月5日 ..:: ブログ ::..   ログイン


 ASP.NET AJAX
[ASP.NET AJAX] Timer コントロールは UpdatePanel の外に配置しよう
By : Akira INOUE   Date : 2007/05/19 18:59

ASP.NET AJAX Extensions の Timer コントロールを使用する場合には、UpdatePanel コントロールの内部に配置すべきではないようです。

いくつか、UpdatePanel 内に Timer コントロールを配置してる例もありますが、可能なら Timer コントロールは UpdatePanel の外に配置して、UpdatePanel の Triggers コレクションで Timer の Tick イベントをトリガに設定しましょう

以下は、Timer を UpdatePanel 内に配置したサンプルです。

Timer1.jpg

aspxファイル

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
  Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
                      "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>TimerSample1CS</title>
</head>
<body>
  <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    <div>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
      <ContentTemplate>
        <asp:Timer ID="Timer1" runat="server" Interval="5000"
                                              OnTick="Timer1_Tick">
        </asp:Timer>
        <asp:Label ID="Label1" runat="server" Text="未更新"></asp:Label>
      </ContentTemplate>
    </asp:UpdatePanel>
    </div>
  </form>
</body>
</html>

C#コードビハインドファイル

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
public partial class _Default : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
  }

  protected void Timer1_Tick(object sender, EventArgs e)
  {
    Label1.Text = DateTime.Now.ToString();
  }
}

これを実行すると下図のように5秒間隔で時刻表示が更新されます(図ではちょっとわかりづらいですが)。

Timer2.jpg

ここで、5秒ごとにサーバとどのような通信がおこなわれているか見てみます。

ちなみに、ツールには Web Development Helper を使っています。
http://projects.nikhilk.net/Projects/WebDevHelper.aspx

Web Development Helper のログは以下のようになります。

Timer3.jpg

2回の Tick イベントによるサーバとの通信をキャプチャしていますが、1回の非同期ポストバックで2回の通信がおこなわれています

Default.aspx は当然ですが、その後の ScriptResource.axd?d=... は何でしょうか?
実はこれ、Microsoft AJAX Library の MicrosoftAjaxTimer.js という JavaScript ファイルです。

Timer コントロールは、サーバサイドで Sys.UI._Timer という JavaScript ライブラリに置き換えられ、クライアントサイドで実行されます。通常は、ページのロード時に1回だけスクリプトがダウンロードされれば済むわけですが、ここでは UpdatePanel 内に Timer コントロールを配置したことにより、UpdatePanel 内部のコントロールは非同期ポストバックで常にレンダリングされ、その対象に Timer コントロールも含まれてしまっているわけです。

これでも、更新間隔が非常に長かったり、負荷が問題にならない状況でしたら良いのでしょうが、なんか無駄ですよね。

この無駄をなくすには、次のように Timer コントロールを UpdatePanel の外に配置して、UpdatePanel の Triggers コレクションで Timer の Tick イベントをトリガに設定することで回避できます。

Timer4.jpg

aspxファイル

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
  Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
                      "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>TimerSample1CS</title>
</head>
<body>
  <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    <div>
      <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
          <asp:Label ID="Label1" runat="server" Text="未更新"></asp:Label>
        </ContentTemplate>
        <Triggers>
          <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
        </Triggers>

      </asp:UpdatePanel>
      <asp:Timer ID="Timer1" runat="server" Interval="5000"
                                            OnTick="Timer1_Tick">
      </asp:Timer>
    </div>
  </form>
</body>
</html>

Image5.jpg

今度は、Web Development Helper のログは以下のようになり、Default.aspx のみの通信となり、毎回 MicrosoftAjaxTimer.js ファイルがダウンロードされることがなくなりました。

Image6.jpg

この Timer コントロールは、Interval の単位がミリ秒だったりと(実際は1秒以下のポストバックは発生しないようですが)、サーバ負荷を十分考慮した設計をしないと、とんでもないことになりますので注意しましょう。

 


[ASP.NET AJAX] ASP.NET Futures の Managed JScript を試す
By : Akira INOUE   Date : 2007/05/17 11:24

ちょっと AJAX と XML-Script 関連で調べたいことがあったので、先日リリースされた ASP.NET Futures (May 2007) をインストールしてみました。

ツールボックスには、次のようなコントロール群が登録されます。

Futures0.jpg

 

また、Web サイトの新規作成では、テンプレートに

  • ASP.NET Futures AJAX Web Site
  • ASP.NET Futures Web Site
  • Dynamic Data Web Site

の3つが新たに登録されていました。

さらに、言語には

  • IronPython
  • Managed JScript

の2つが新たに出現(うおーっ!)。

Futures1.jpg

 

早速、Managed JScript やらを試してみました。

テンプレートには「ASP.NET Futures AJAX Web Site」を選択して、新規Webサイトを作成。

ソリューションには、次のようなファイルが現れました。

Futures2.jpg

拡張子 *.jsx が、Managed JScript のサーバサイドのスクリプトコードです。


とりあえず、よくあるパターンで TextBox, Label, Button, UpdatePanel を配置して・・・

Futures3.jpg

Default.aspx はこんな感じ。

<%@ Page Language="ManagedJScript" CodeFile="Default.aspx.jsx"
    Inherits="Microsoft.Web.Scripting.UI.ScriptPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  <title>Untitled Page</title>
</head>
<body>
  <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    <div>
   <asp:TextBox ID="TextBox1" runat="server" Width="250px"></asp:TextBox>
  <asp:UpdatePanel ID="UpdatePanel1" runat="server">
   <ContentTemplate>
    <asp:Label ID="Label1" runat="server" Width="250px"></asp:Label>
<br />
    <asp:Button ID="Button1" runat="server" Text="Click Me!" />
   </ContentTemplate>
  </asp:UpdatePanel>
 </div>
  </form>
</body>
</html>

Default.aspx.jsx はこんなコーディングをして、

function Page_Load(sender, e){
  if (Page.IsPostBack){
    Label1.Text = "Hello " + TextBox1.Text + " !!";
  }
}

さて、実行。

Futures4.jpg

ちゃんと動きました~。

#さて、本題をやらないと・・・


[AJAX Control Toolkit] Popup 関連のコントロールが IE 100%表示以外で位置がずれる
By : Akira INOUE   Date : 2007/04/09 11:25

ASP.NET 2.0 AJAX の応用として CodePlex にてリリースされている AJAX Control Toolkit には、多くの有用なコントロールが含まれています。

AJAX Control Toolkit
http://www.codeplex.com/AtlasControlToolkit

ただ、PopupControl 関連のコントロールには、現在のバージョン(2007-03-01 Release)では Internet Explorer のページ倍率を 100% 以外にすると、ポップアップウィンドウの表示位置がずれてしまい正しく表示されない不具合があるようです。

例えば、下記のページ
http://ajax.asp.net/ajaxtoolkit/Calendar/Calendar.aspx
の Calendar コントロール (CalendarExtender) のデモで試してみると、IE の表示倍率が 100% の場合はカレンダーが正しい位置にポップアップされます。

Cal100.jpg
Fig : CalendarExtender (IE 100% View)

しかし、例えば 125% 表示で試すと、カレンダーの表示位置が正しい位置より、より大きくオフセットされて表示されてしまいます。

Cal125.jpg
Fig : CalendarExtender (IE 125% View)

 

DropDown コントロール (DropDownExtender)
http://ajax.asp.net/ajaxtoolkit/DropDown/DropDown.aspx
でも、以下のようになってしまいます。

Drop100.jpg
Fig : DropDownExtender (IE 100% View)

 

Drop125thumb.jpg
Fig : DropDownExtender (IE 125% View)

正式に Fix されるまで、使用には注意が必要です。

 


[ASP.NET AJAX] クライアントスクリプトからの Web サービスの非同期呼び出し
By : Akira INOUE   Date : 2007/03/28 20:31

ASP.NET AJAX をいろいろと調べていまして、そのメモを兼ねて一つ記事をアップします。

[The Official Microsoft ASP.NET 2.0 Site] にあるサンプル
「How Do I: ASP.NET AJAX Enable an Existing Web Service?」
http://www.asp.net/learn/videos/view.aspx?tabid=63&id=82

などでは、

function Button1_onclick() {
ret = SimpleService.SayHello(document.getElementById('Text1').value,
                             OnComplete, OnTimeOut, OnError);
return(true);
}

などと、Web メソッドの非同期呼び出しを記述しています。

幸いなこと(?)に JavaScript ではエラーとならずに実行されるのですが、正確にはこの記述は間違いです(以前の Atlas 時代の形式です)ので注意してください。

正確には、プロキシを使った Web サービスの呼び出しのプロトタイプは

myServiceProxy.MyServiceMethod(param1, ... , paramN,
               SucceededCallback, FailedCallback, userContext)

となっています。

参考:Generated Proxy Classes Web Service Methods
http://ajax.asp.net/docs/ClientReference/Sys.Net/GeneratedProxyClasses/
WebServiceMethods.aspx

サンプルのままだと、コールバック関数の OnComplete は問題ないのですが、タイムアウトでの処理のつもりで書いたコールバック関数 OnTimeOut がエラー発生時にも呼び出されてしまいます。

最新の ASP.NET AJAX では、タイムアウトとエラー発生時のコールバックは統一されており、同じ関数が呼び出されるようになっています(プロトタイプでは FailedCallback 引数に指定した関数)。

私は、このサンプルのデモムービーを見ていて、ちょっと混乱しました・・・


さて、参考までに・・・

ASP.NET AJAX を使って、クライアントサイドのスクリプトから Web サービスを呼び出すには、Web サービスのメソッドに System.Web.Script.Services 名前空間の ScriptService 属性 (ScriptServiceAttribute)が必要となります。

[ SimpleService.cs ]

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class SimpleService : System.Web.Services.WebService
{
  [WebMethod]
  public string SayHello(string name)
  {
    return "Hello : " + name;
  }
}

そして、aspx ソースに asp:ScriptManager を追加して、その子要素に Services/asp:ServiceReference を下記のように追加すると、Web サービスの呼び出しに必要な JavaScript プロキシコードが生成されます。

[ Default.aspx ]

<asp:ScriptManager runat="server" ID="scriptManager">
  <Services>
    <asp:ServiceReference Path="SimpleService.asmx" />
  </Services>
  <Scripts>
    <asp:ScriptReference Path="UsingSimpleService.js" />
  </Scripts>
</asp:ScriptManager>

生成されたプロキシスクリプトを使うと、クライアントサイドのスクリプトで Web サービスの非同期の呼び出しが、下記のコードのように簡単に行えるようになります。

[ UsingSimpleService.js ]

function pageLoad()
{
  SimpleService.set_timeout(3000);
  SimpleService.set_defaultUserContext("Default context");
  SimpleService.set_defaultSucceededCallback(SucceededCallback);
  SimpleService.set_defaultFailedCallback(FailedCallback);
}

function Button1_onclick()
{
  SimpleService.SayHello(document.getElementById("Text1").value);
}

function Button2_onclick()
{
  SimpleService.SayHello(document.getElementById("Text1").value,
                         SucceededCallback,
                         FailedCallback,
                         "User context");
}

function SucceededCallback(result, userContext, methodName)
{
  var text = result + " (" + userContext + ")" + " [" + methodName + "]";

  document.getElementById("Label1").innerText = text;
}

function FailedCallback(error, userContext, methodName)
{
  var text = "Service Error : " +  error.get_message() +
             " (" + userContext + ")" + " [" + methodName + "]";

  document.getElementById("Label1").innerText = text;
}

このプロキシを使った Web サービスの呼び出しでは、pageLoad で行っているように、プロキシの set_defaultXXXX メソッドで、コールバック関数を指定して Button1_onclick で Web サービスメソッドの呼び出しのみを行う方法と、Button2_onclick で行っているように Web サービスの呼び出し時にコールバック関数を指定することもできます。

ここで、プロキシを使った Web サービスの呼び出しのプロトタイプは前述のように

myServiceProxy.MyServiceMethod(param1, ... , paramN,
               SucceededCallback, FailedCallback, userContext);

となります。

また、各コールバック関数のプロトタイプは下記の通りとなります。

function SucceededCallback(result, userContext, methodName);
function FailedCallback(error, userContext, methodName);


ASP.NET AJAX は、UpdatePanel を使えばとても簡単に Web アプリケーションの AJAX 化ができるのですが、本格的な ASP.NET AJAX アプリケーションを作り始めると、やはりいろいろと奥が深いところがあり楽しいですね。

【参考】
Generated Proxy Classes
http://ajax.asp.net/docs/ClientReference/Sys.Net/GeneratedProxyClasses/default.aspx

 



MCAD


techbank.jp


Copyright © 2005-2008 by BitWiz   使用条件  プライバシー