|
|
@ OutputCacheディレクティブを使用して出力ページを保持する |
|
ASP.NETでは、要求が送信されるたびに新しいページが生成され、利用者側に返します。しかし、要求も前回と同じで、出力するページがまったく同じ内容の場合、毎回新しく生成するのはサーバに負担を与えかねません。例えば、トップページなどのよく使用するページは一定期間保持するように設定しておき、同じページを出力する際は保存しておいたページを表示するようにすればサーバの負担は軽減されますよね。これを実現するのがキャッシュと呼ばれる機能で、一定期間ページを保持するように設定することができます。設定した時間が過ぎた場合は従来どおり新しいページが生成され、同じように一定期間の間ページを保持します。
では、早速キャッシュを使用してみましょう。メニューバーから「ファイル」→「新規作成」→「Webサイト」を選び、ASP.NET Webサイトを追加します。プロジェクト名は自由に設定してください。
「Default.aspx.cs」ファイルを開き、コードを以下のように変更してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
using System.Web.Caching;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(DateTime.Now);
}
} |
まだこの段階ではキャッシュを使用していません。19行目ではDateTimeクラスのNowメソッドを使用して現在時刻を取得し、Webページに出力するようコーディングしています。
プログラムを実行させてみましょう。実行結果は以下のようになります。
従来通り、プログラムが実行された現在時刻が表示されています。ここでブラウザの更新ボタンを押してみましょう。実行結果は以下のように変わっているはずです。
時間が変わっているのは、ページが読み込まれる度に新しいページを生成しているからです。次は、実際にキャッシュを実装してプログラムを実行してみましょう。
キャッシュを実装するには、ディレクティブを使用して設定を行います。ディレクティブとは、ページを処理する際に使用する設定を示す為に必要な構文のことで、「Default.aspx」ファイルに追加します。ディレクティブは以下のような構文になっています。
1
|
<%@ ディレクティブの種類 属性1="値1" 属性2="値2" %> |
ディレクティブの種類には設定を変更したいディレクティブの種類を、属性にはそれぞれのディレクティブが持つ設定項目を記述します。なお、属性は複数個指定することができ、属性の値はセミコロン「"」で囲みます。
キャッシュのコントロールは「@ OutputCacheディレクティブ」を使用します。早速キャッシュを実装できるようコードを修正してみましょう。「Default.aspx」ファイルをソースビューで開いてください。次に、「Default.aspx」の内容を以下のように変更します。(2行目を追加します)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ OutputCache Duration="20" VaryByParam="none" %>
<!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>無題のページ</title> </head> <body bgcolor="White" link="#ffffff" vlink="#999999"> <form id="form1" runat="server"> <div> </div> </form> </body> </html> |
「@ OutputCacheディレクティブ」が持つ「Duration」属性は、何秒間キャッシュを保持しておくかを定めるもので、今回の例では20秒間ページを保持しておくように記述しています。「VaryByParam」属性は必ず書かないとエラーになるため、明示的に「none」を設定しています。
それでは実際にこのプログラムを実行してください。実行結果は以下のようになるはずです。
実行結果
20秒以内に更新を押した場合
20秒以上経った後に更新を押した場合
20秒以内に更新ボタンを押した場合、キャッシュ機能によってページが保持されているので値が変更されていないのがわかります。20秒以上経った後に更新ボタンを押すと、ページが破棄されている為、新しくページが生成され再度現在時刻の取得をしています。
なお、「@ OutputCache」ディレクティブの「Duration」属性で指定したページの保持は、ページがキャッシュされてから破棄されるまでの時間を表しています。読み込まれる度、20秒後に設定しているわけではありませんので注意してください。
|
|
新しいページをプロジェクトに追加する |
|
VisualStudioでは、ひとつのプロジェクトで複数のWebページを管理することができます。新しいWebページをプロジェクト内に追加するには、メニューバーから「Webサイト」→「新しい項目を追加」をクリックします。
「新しい項目の追加」ウィンドウ
今回はWebページをもうひとつ追加しましょう。テンプレートの中から「Webフォーム」を選択し、名前は「Default2.aspx」に設定します。Webページを追加すると、エクスプローラウィンドウに「Default2.aspx」ファイルと「Default2.aspx.cs」ファイルが生成されているのがわかります。
生成された「Default.aspx」ファイルと「Default2」ファイル
プロジェクト内にある別のページへリンクを設定するには、ボタンコントロールなどのクリックイベントにResponseクラスのRedirectメソッドを実装します。
1
|
Response.Redirect("Default.aspx"); |
ResponseクラスのRedirectメソッドには、引数としてリンク先として設定したいWebページへのアドレスか同じプロジェクト内のファイル名を指定します。
「Default.aspx」ファイルから「Default2.aspx」ファイルにアクセスできるようリンクを設定しましょう。「Default.aspx」ファイルをWebフォームデザイナで開き、ボタンをひとつ設置してください。
ここではボタンコントロール名を「Button1」に設定し、ボタンの「Text」プロパティを「次へ」に変更しておきます。
ボタンコントロールをひとつ配置する
次はこの「Button1」コントロールにリンクを設定します。「Button1」コントロールをダブルクリックしてクリックイベントを作成し、「Default.aspx.cs」ファイルの内容を以下のように変更します。(23行目を追加します)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
using System.Web.Caching;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("Default.aspxファイルです");
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Redirect("Default2.aspx");
}
} |
23行目のコードでは、実際に「Redirect」メソッドを使用して「Button1」コントロールがクリックされたときに「Default2.aspx」ファイルを開くようにコーディングしています。
複数のページをプロジェクト内に作成した場合は、どのページを一番最初に表示するページにするかをあらかじめ決めておく必要があります。一番最初に表示されるWebページを設定するには、エクスプローラウィンドウからスタートページに設定したいファイルを右クリックし、表示されたコンテキストメニューの中から「スタートページに設定」を選択します。 ここでは、「Default.aspx」ファイルを右クリックしてスタートページに設定しておきましょう。
最後に「Default2.aspx.cs」ファイルを開き、コードの内容を以下のように変更してください。(18行目を追加)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("Default2.aspxファイルです");
}
} |
これは「Default2.aspx」ファイルが開かれたことをわかりやすくするために、ページが読み込まれた段階で文字列を表示するように記述しました。このプログラムを実行すると、実行結果は以下のようになります。
最初の実行結果
「次へ」ボタンを押した後に開かれたページ
表示されたテキストを確認すると、確かに「Default2.aspx」に対しリンクが設定されていたのがわかります。ひとつのプロジェクト内に複数のWebページを作成すれば、表示させたいコンテンツにあったデザインでWebページを表示させることができます。
|
|
Cacheクラスを使用したキャッシュ管理 |
|
先程は複数のページをプロジェクト内に作成する方法を解説しましたが、別のフォームから入力された値を引き継ぐにはどのようにすれば良いのでしょうか?ASP.NETでは複数のページでデータを共有するときのために「Cache」クラスが提供されており、この「Cache」クラスを使えば一定期間値やインスタンスを保持しておくことができます。
今までのファイルを引き継いで、「Cache」クラスを使用したWebアプリケーションを作成してみましょう。まずはフォーム画面を作成しますので、「Default.aspx」ファイルをWebフォームデザイナで開き、以下のようにテキストボックスを3つ追加してください。
「テキストコントロールを」配置する
コントロール名は、上から順番に「TextBox1」、「TextBox2」、「TextBox3」に設定します。ボタンコントロールはそのままで構いません。
次に、「Default.aspx.cs」ファイルを開き、コードを以下のように変更してください。(Page_Loadイベントの内容を削除し、Button_1Clickイベントの内容を変更します)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
using System.Web.Caching;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
String[] str = new String[3];
str[0] = TextBox1.Text;
str[1] = TextBox2.Text;
str[2] = TextBox3.Text;
Cache.Insert("log", str, null, Cache.NoAbsoluteExpiration,
TimeSpan.FromSeconds(20), CacheItemPriority.Default, null);
Response.Redirect("Default2.aspx");
}
} |
23行目では、テキストボックスから入力された値を保持するための配列を宣言し、初期化をしています。このコードの27行目で行われているのがキャッシュの実装です。「Cache.Insert」メソッドは、以下のように使用します。
1
2
|
Cache.Insert(キー値, 保持するオブジェクト, 依存関係ポリシー, 有効期限ポリシー(絶対時間),
有効期限ポリシー(相対時間), 優先度ポリシー, デリゲート); |
キャッシュとして保持するオブジェクトは、ハッシュテーブルによって管理されています。ハッシュテーブルとは、配列の各要素にアクセスするために使用されるインデックスの代わりに「キー」を指定してアクセスできるデータ構造のことで、連想配列とも呼ばれます。キーには文字列を指定できることから、このような呼び方をされます。このメソッドの第一引数では、値を格納するためのキー値を設定しています。第2引数では、実際に第1引数で指定したキー値に保持させるオブジェクトを指定しています。
第3引数の依存関係ポリシーでは、指定したファイルが変更されたときにキャッシュを破棄するよう設定することができます。例えば、外部のXMLファイルやデータベースからキャッシュを生成した場合、他の処理系統からこのファイルの内容が変更されてしまうとWebページに表示する内容は古いものとなってしまいます。外部のファイルからキャッシュを生成する際は最新のデータを保つためにも積極的に指定するようにしましょう。なお、特に指定する必要がなければ引数として「null」を設定します。
第4引数、第5引数はどちらか一方を設定します。有効期限ポリシーでは、絶対時間(キャッシュが生成されてから破棄までの期限)、あるいは相対時間(最後にキャッシュにアクセスしてから破棄までの期限)を指定できます。相対時間による指定に関してはスライド式の有効期限となっていますので、20秒後に設定すればキャッシュにアクセスするたびに有効期限が20秒後に再設定されます。絶対時間による指定に関しては、アクセスに関係なく、指定した有効期限に必ず削除されます。絶対時間を指定しない場合は「Cache.NoAbsoluteExpiration」を、相対時間を指定しない場合は「Cache.NoSlidingExpiration」を引数として指定し、有効期限を指定しないことを示します。
有効期限ポリシーは、キャッシュの優先順位を示します。有効期限ポリシーで指定したキャッシュの有効期限は、メモリ不足やシステムの状況に応じていつ無効化されるかは必ずしも約束されていません。このときに行われるキャッシュの開放の事を「清掃」と呼びます。ここでは、システムが清掃プロセスによってキャッシュを開放するときの優先順位を指定することができます。標準は「Default」で、「High」に設定すると削除されにくくなり、「Low」に設定するとキャッシュから削除されやすくなります。
デリゲートでは、キャッシュが削除されたときに呼び出されるデリゲートを指定することができます。キャッシュが削除されたときにシステムに対して何らかの通知を行いたい場合はここに指定します。
今回は、最後にキャッシュにアクセスしてから20秒間は内容を保持するように指定し、「log」キーに各テキストボックスの内容を格納した配列「str」をキャッシュに追加しています。
次に、「Default2.aspx」ファイルをWebフォームデザイナで開き、「Literal」コントロールを以下のように3つ追加してください。
「Literal」コントロールを3つ配置する
「Literal」コントロールの名前は、上から順番に「Literal1」、「Literal2」、「Literal3」に設定します。
最後にキャッシュから値を取り出すよう「Default2.aspx.cs」ファイルをコーディングしていきます。「Default2.aspx.cs」ファイルのコードを以下のように変更してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Cache["log"] != null)
{
String[] str = (String[])Cache["log"];
Literal1.Text = str[0];
Literal2.Text = str[1];
Literal3.Text = str[2];
}
else
{
Response.Write("キャッシュは削除されています");
}
}
} |
18行目では、キー値が「log」のキャッシュが存在しているかどうかをifステートメントで確認しています。特定のキャッシュにアクセスするには
といったように記述し、指定したキーにキャッシュが存在しない場合は「null」が返されます。このように、配列のインデックス名の変わりに文字列を指定できるのがハッシュテーブルの特徴です。
20行目では、ハッシュテーブルの中からキー値が「log」の内容をString型の配列に代入するよう記述しています。ハッシュテーブルに格納されているオブジェクトは、異なる型のインスタンスを保持できるようObject型にアップキャストされていますので、代入時は明示的に型を指定してダウンキャストする必要があります。
このプログラムを実行すると、以下のようになります。
フォームの内容
フォームの内容が引き継がれたDefault2.aspxファイル
最後のアクセスから20秒以上経過した場合
ページが実際に「Default2.aspx」ファイルに移ると、先程「Default.aspx」ファイルで入力されたフォームの内容がキャッシュを通して「Default2.aspx」ファイルに反映されています。20秒以上経った後に「Default2.aspx」ファイルを更新すると、「Literal」コントロールに何も表示されなくなり、キャッシュからlogの内容が削除されているのがわかります。
キャッシュを使用する場合は、必ずifステートメントを使用して取り出そうとしているキャッシュが存在するかどうかをチェックするようにしましょう。今回のプログラムで記述したifステートメントを省略すると、配列「str」に代入するキャッシュが存在しないため、例外が発生してしまいます。また、nullチェックでキャッシュが存在しなかった際は、ユーザビリティを考慮してページの有効期限が切れたことを示すページを表示するよう実装しましょう。 |