この章では、Coherence for .NETライブラリを使用する簡単なWindows ASP.NET Webアプリケーションを作成する手順について説明します。
この章の内容は次のとおりです。
ASP.NET Webアプリケーションを作成する手順は、次のとおりです。
Visual Studio 2005で「ファイル」→「新規作成」→「Web サイト」を選択します。
「テンプレート」の「ASP.NET Web サイト」を選択します。
最も使い慣れている開発言語を選択します。
アプリケーションを保存する場所(タイプとフルパス)を選択します。
「OK」ボタンをクリックすると、新しいソリューションと空のASP.NETアプリケーションが生成されます。
.NETアプリケーションでCoherence for .NETライブラリを使用するには、Coherence.dll
ライブラリに対する参照を追加します。
プロジェクトで「プロジェクト」→「参照の追加」を選択するか、「ソリューション エクスプローラ」の「参照設定」を右クリックして「参照の追加」を選択します。
「参照の追加」ウィンドウで「参照」タブを選択し、ファイル・システム上のCoherence.dll
ライブラリを探します。
「OK」をクリックします。
Coherence for .NETライブラリを正しく構成するには、ライブラリで使用される各構成ファイルの適切なファイル名を指定したWeb.config
XMLファイルを構成する必要があります。例25-1は、有効なWeb.config
構成ファイルを示しています。
例25-1 Web.config構成ファイルのサンプル
<?xml version="1.0"?> <configuration> <configSections> <section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence, Version=3.6.0.0, Culture=neutral, PublicKeyToken=0ADA89708FDF1F9A"/> </configSections> <coherence> <cache-factory-config>web://~/Config/coherence.xml</cache-factory-config> <cache-config>web://~/Config/cache-config.xml</cache-config> <pof-config>web://~/Config/pof-config.xml</pof-config> </coherence> <appSettings/> <connectionStrings/> <system.web> <globalization culture="en-US" uiCulture="en-US"/> <sessionState mode="Custom" customProvider="CoherenceSessionProvider" timeout="20"> <providers> <add name="CoherenceSessionProvider" type="Tangosol.Web.CoherenceSessionStore, Coherence, Version=3.6.0.0, Culture=neutral, PublicKeyToken=0ADA89708FDF1F9A"/> </providers> </sessionState> <compilation debug="false" defaultLanguage="c#"> <assemblies> <add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="Coherence, Version=3.6.0.0, Culture=neutral, PublicKeyToken=0ADA89708FDF1F9A"/> </assemblies> </compilation> <authentication mode="Windows"/> <customErrors mode="Off"/> </system.web> </configuration>
<configSections>
には、Coherence for .NETの構成セクションへのアクセスを処理するクラスを指定する必要があります。
Coherence for .NETの構成セクションの要素は次のとおりです。
cache-factory-config
: CacheFactory
で使用するIConfigurableCacheFactoryおよびLoggerを構成するために、CacheFactory
で使用される構成ディスクリプタのパスを記述します。
cache-config
: 前述のキャッシュ構成(「クライアントでのCoherence*Extendの構成」を参照)を含むキャッシュ構成ディスクリプタのパスを記述します。このキャッシュ構成ディスクリプタは、DefaultConfigurableCacheFactoryで使用されます。
pof-config
: アプリケーションで使用するカスタム型を登録するために、ConfigurablePofContext
で使用される構成ディスクリプタのパスを記述します。
例25-2は、coherence.xml
構成ファイルのサンプルを示しています。
例25-2 coherence.xml構成ファイルのサンプル
<?xml version="1.0"?> <coherence xmlns="http://schemas.tangosol.com/coherence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.tangosol.com/coherence assembly://Coherence/Tangosol.Config/coherence.xsd"> <logging-config> <destination>stderr</destination> <severity-level>5</severity-level> <message-format>{date} <{level}> (thread={thread}): {text} </message-format> <character-limit>8192</character-limit> </logging-config> </coherence>
例25-3は、cache-config.xml
構成ファイルのサンプルを示しています。
例25-3 cache-config.xml構成ファイルのサンプル
<?xml version="1.0"?> <cache-config xmlns="http://schemas.tangosol.com/cache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.tangosol.com/cache assembly://Coherence/Tangosol.Config/cache-config.xsd"> <caching-scheme-mapping> <cache-mapping> <cache-name>dist-contact-cache</cache-name> <scheme-name>extend-direct</scheme-name> </cache-mapping> <cache-mapping> <cache-name>aspnet-session-storage</cache-name> <scheme-name>extend-direct</scheme-name> </cache-mapping> <cache-mapping> <cache-name>aspnet-session-overflow</cache-name> <scheme-name>extend-direct</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <remote-cache-scheme> <scheme-name>extend-direct</scheme-name> <service-name>ExtendTcpCacheService</service-name> <initiator-config> <tcp-initiator> <remote-addresses> <socket-address> <address>localhost</address> <port>9099</port> </socket-address> </remote-addresses> </tcp-initiator> <outgoing-message-handler> <request-timeout>30s</request-timeout> </outgoing-message-handler> </initiator-config> </remote-cache-scheme> </caching-schemes> </cache-config>
例25-4は、pof-config.xml
構成ファイルのサンプルを示しています。
例25-4 pof-config.xml構成ファイルのサンプル
<?xml version="1.0"?> <pof-config xmlns="http://schemas.tangosol.com/pof" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.tangosol.com/pof assembly://Coherence/Tangosol.Config/pof-config.xsd"> <user-type-list> <!-- include all "standard" Coherence POF user types --> <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml </include> <!-- include all application POF user types --> <user-type> <type-id>1001</type-id> <class-name>ContactCache.Web.ContactInfo</class-name> </user-type> </user-type-list> </pof-config>
これらの構成ファイルを作成すると、Coherenceクラスタに接続する準備が完了し、Coherence for .NETでサポートされるすべての操作を実行できるようになります。
Default.aspx
ページの「デザイン」タブに切り替えて、「ツールボックス」ペインから適切なコントロールをドラッグ・アンド・ドロップでページに追加します。Name
、Street
、City
、State
およびZip
の各フィールドには、TextBoxコントロールおよび対応するLabelコントロールが必要です。これを図25-2に示します。
ページにコントロールを配置したら、各コントロールのIDおよびTextプロパティを変更する必要があります。コード内ではラベルを使用しないため、ラベルのIDプロパティ値は生成時のままにして、Textプロパティにのみ適切な値を入力します。IDおよびTextBoxコントロールには、txtName
、txtStreet
などの名前を付けます。ボタンを1つ追加し、そのIDをbtnSave
に、TextプロパティをSaveに変更します。これを図25-3に示します。
ボタンを1つ追加し、そのIDをbtnClear
に、TextプロパティをClear
に変更します。これを図25-4に示します。
label
を追加し、そのIDをlblTotal
に変更します。このラベルはキャッシュ・サイズの表示に使用されます。「ツールボックス」ペインの「検証」コントロール・リストからRequiredFieldValidator
を追加して、そのプロパティを設定します。これを図25-5に示します。
ControlToValidate
プロパティがtxtNameコントロールに設定されていることに注意してください。
「ツールボックス」ペインの「データ」コントロール・リストから、GridViewコントロールとObjectDataSource
(名前はdsContact)を追加します。これを図25-6に示します。
例25-5は、GridView
コントロール・ソースのコードを示しています。
例25-5 GridViewデータ・コントロールのコード
<asp:GridView ID="gridCache" runat="server" DataSourceID="dsContact" AutoGenerateColumns="False" Font-Names="Verdana"> <Columns> <asp:TemplateField> <ItemStyle Font-Size="Small"/> <ItemTemplate> <asp:HyperLink Text="[Remove]" ID="HyperLink1" runat="server" NavigateUrl='<%# "?removeKey=" + DataBinder.Eval(Container.DataItem, "Name").ToString() %>'/> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Name"> <HeaderStyle BackColor="#DCE7F7"/> <ItemTemplate> <asp:HyperLink runat="server" NavigateUrl='<%# "?getKey=" + DataBinder.Eval(Container.DataItem, "Name").ToString() %>'> <%# DataBinder.Eval(Container.DataItem, "Name") %> </asp:HyperLink> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="Street" HeaderText="Street"> <HeaderStyle BackColor="#DCE7F7"/> </asp:BoundField> <asp:BoundField DataField="City" HeaderText="City"> <HeaderStyle BackColor="#DCE7F7"/> </asp:BoundField> <asp:BoundField DataField="State" HeaderText="State"> <HeaderStyle BackColor="#DCE7F7"/> </asp:BoundField> <asp:BoundField DataField="Zip" HeaderText="Zip"> <HeaderStyle BackColor="#DCE7F7"/> </asp:BoundField> </Columns> </asp:GridView>
例25-6は、ObjectDataSource
のコードを示しています。
例25-6 ObjectDataSourceのコード
<asp:ObjectDataSource ID="dsContact" runat="server" SelectMethod="GetData" TypeName="ContactCache.Web.ContactInfoDataSource" </asp:ObjectDataSource>
ここで、フィルタ列用にDropDownListを1つ、フィルタ基準用にTextBoxを1つドラッグ・アンド・ドロップして「Search」ペインを追加します。これを図25-7に示します。
この項の内容は次のとおりです。
ASP.NETアプリケーションが終了したときにクラスタのリソースを解放するために、Global.asax
に記述したApplication_End
イベント・ハンドラでCacheFactory.Shutdown()
をコールする必要があります。例25-7は、この処理を実行するGlobal.asax
ファイルを示しています。ここでは、例外が発生したときにエラー・ページを表示するためのコールも追加しています。
例25-7 エラー・ページへのユーザーのリダイレクト
<%@ Application Language="C#" %> <script runat="server"> void Application_Start(object sender, EventArgs e) { try { Application["contactCache"] = CacheFactory.GetCache("dist-contact-cache"); } catch { } } void Application_End(object sender, EventArgs e) { CacheFactory.Log("Application terminated.", CacheFactory.LogLevel.Info); INamedCache contactCache = Application["contactCache"] as INamedCache; if (contactCache != null) { contactCache.Release(); } CacheFactory.Shutdown(); } void Application_Error(object sender, EventArgs e) { Server.Transfer("ConnectionError.html"); } </script>
例25-8は、ContactInfo
ビジネス・オブジェクトの定義を示しています。
例25-8 ビジネス・オブジェクトの定義ファイルのサンプル
public class ContactInfo : IPortableObject { private string name; private string street; private string city; private string state; private string zip; public ContactInfo() { } public ContactInfo(string name, string street, string city, string state, string zip) { this.name = name; this.street = street; this.city = city; this.state = state; this.zip = zip; } public void ReadExternal(IPofReader reader) { name = reader.ReadString(0); street = reader.ReadString(1); city = reader.ReadString(2); state = reader.ReadString(3); zip = reader.ReadString(4); } public void WriteExternal(IPofWriter writer) { writer.WriteString(0, name); writer.WriteString(1, street); writer.WriteString(2, city); writer.WriteString(3, state); writer.WriteString(4, zip); } }
例25-9は、データをデータ・バインド・コントロールに提供するクラスを示しています。データのICollection
をデータ・バインド・コントロールに返す、publicのGetData()
メソッドが必要です。
例25-9 データ・バインド・コントロールへのデータの提供
public class ContactInfoDataSource { public ICollection Data { set { m_col = value; } } public ICollection GetData() { return m_col; } public ContactInfoDataSource() {} public ContactInfoDataSource(ICollection col) { ArrayList results = new ArrayList(); if (col is INamedCache) { INamedCache cache = col as INamedCache; foreach (ContactInfo contactInfo in cache.Values) { results.Add(contactInfo); } } else if (col is ArrayList) { foreach (DictionaryEntry entry in col) { results.Add(entry.Value); } } Data = results; } private ICollection m_col = null; }
データをデータ・バインド・コントロールに提供する内部オブジェクトを作成するイベント・ハンドラを追加します。これを例25-10に示します。
例25-10 データをデータ・バインド・コントロールに提供するイベント・ハンドラ
protected void dsContact_ObjectCreating(object sender, ObjectDataSourceEventArgs e) { ContactInfoDataSource cds = new ContactInfoDataSource(Contacts == null ? ContactCache : Contacts); e.ObjectInstance = cds; }
例25-11のメソッドは、ページに表示されたGridView
をリフレッシュし、合計ラベルlblTotal
をリフレッシュして、キャッシュ内にオブジェクトがある場合にbtnClear
およびすべてのボタンを表示します。
例25-11 グリッド・ビューをリフレッシュするメソッド
private void RefreshDataGridAndRenderPage() { gridCache.DataBind(); int totalObjects = (Contacts == null ? ContactCache.Count : Contacts.Count); lblTotal.Text = "Total objects: " + totalObjects; if (ContactCache.Count > 0) { lblTotal.Visible = btnClear.Visible = true; lblSearch.Visible = listColumnNames.Visible = lblFor.Visible = txtFilterCriteria.Visible = btnSearch.Visible = true; } else { lblTotal.Visible = btnClear.Visible = false; lblSearch.Visible = listColumnNames.Visible = lblFor.Visible = txtFilterCriteria.Visible = btnSearch.Visible = false; } btnClearFilter.Visible = (Contacts != null); }
例25-12のメソッドは、ページ・ロード・イベントを処理します。Request
にgetKey
値が存在する場合は、指定キーにマップされた値がキャッシュから取得され、そのプロパティが適切なフィールドに移入されます。Request
にremoveKey
値が存在する場合は、指定キーにマップされた値がキャッシュから削除されます。
例25-12 ページ・ロード・イベントを処理するメソッド
protected void Page_Load(object sender, EventArgs e) { if (Request["getKey"] != null) { FindObjectInCache(Request["getKey"]); } else if (Request["removeKey"] != null) { CacheFactory.Log("Object with key [" + Request["removeKey"] + "] has been removed from cache.", CacheFactory.LogLevel.Info); ContactCache.Remove(Request["removeKey"]); } RefreshDataGridAndRenderPage(); PopulateFilterColumns(); }
例25-13に示すヘルパー・メソッドは、指定されたキーに従ってContactInfo
オブジェクトをキャッシュから取得します。
例25-13 指定キーによるビジネス・オブジェクトのキャッシュからの取得
private void FindObjectInCache(object key) { ContactInfo contactInfo = (ContactInfo)ContactCache[key]; if (contactInfo == null) { contactInfo = new ContactInfo(); } txtName.Text = key as String; txtStreet.Text = contactInfo.Street; txtCity.Text = contactInfo.City; txtState.Text = contactInfo.State; txtZip.Text = contactInfo.Zip; }
例25-14は、btnSave
ボタンのイベント・ハンドラを示しています。
例25-14 「Save」ボタンのイベント・ハンドラ
protected void btnSave_Click(object sender, EventArgs e) { String name = txtName.Text; if (name != null && name != "") { ContactInfo contactInfo = new ContactInfo(name, txtStreet.Text, txtCity.Text, txtState.Text, txtZip.Text); ContactCache.Insert(name, contactInfo); CacheFactory.Log("Object with key [" + name + "] has been inserted into cache.", CacheFactory.LogLevel.Info); RefreshDataGridAndRenderPage(); } }
例25-15は、btnClear
ボタンのイベント・ハンドラを示しています。
例25-15 「Clear」ボタンのイベント・ハンドラ
protected void btnClear_Click(object sender, EventArgs e) { NameValidator.Enabled = false; ContactCache.Clear(); RefreshDataGridAndRenderPage(); NameValidator.Enabled = true; }
例25-16は、btnSearch
ボタンのイベント・ハンドラを示しています。
例25-16 「Search」ボタンのイベント・ハンドラ
protected void btnSearch_Click(object sender, EventArgs e) { NameValidator.Enabled = false; String filterBy = listColumnNames.Items[listColumnNames.SelectedIndex].Text; String filterCriteria = txtFilterCriteria.Text.Trim(); if (filterCriteria != "") { IValueExtractor extractor = new ReflectionExtractor("get" + filterBy); IFilter filter = new LikeFilter(extractor, filterCriteria, '\\', true); ICollection results = ContactCache.GetEntries(filter); Contacts = results; dsContact = new ObjectDataSource(); RefreshDataGridAndRenderPage(); } NameValidator.Enabled = true; }
例25-17は、btnClearFilter
ボタンのイベント・ハンドラを示しています。
例25-17 「Clear Filter」ボタンのイベント・ハンドラ
protected void btnClearFilter_Click(object sender, EventArgs e) { NameValidator.Enabled = false; Contacts = null; dsContact = new ObjectDataSource(); RefreshDataGridAndRenderPage(); NameValidator.Enabled = true; }
最後に適切なエラー・メッセージを指定して、プロジェクトにConnectionError.html
ページを追加します。