多くの中からユーザー アカウントを 1 つ選択するインターフェイスを構築する (C#)
このチュートリアルでは、ページングされたフィルター可能なグリッドを使用してユーザー インターフェイスを構築します。 特に、ユーザー インターフェイスは、ユーザー名の開始文字に基づいて結果をフィルター処理するための一連の LinkButtons と、一致するユーザーを表示する GridView コントロールで構成されます。 まず、GridView 内のすべてのユーザー アカウントを一覧表示します。 次に、手順 3 で、LinkButtons フィルターを追加します。 手順 4 では、フィルター処理された結果のページングを確認します。 手順 2 から 4 で構築されたインターフェイスは、後続のチュートリアルで使用して、特定のユーザー アカウントの管理タスクを実行します。
はじめに
「ユーザーへのロールの割り当て」チュートリアルでは、管理者がユーザーを選択してロールを管理するための基本的なインターフェイスを作成しました。 具体的には、インターフェイスは管理者にすべてのユーザーのドロップダウン リストを表示しました。 このようなインターフェイスは、十数個のユーザー アカウントがあるが、数百または数千のアカウントを持つサイトでは扱いにくい場合に適しています。 ページングされたフィルター可能なグリッドは、大規模なユーザー ベースを持つ Web サイトに適したユーザー インターフェイスです。
このチュートリアルでは、このようなユーザー インターフェイスを構築します。 特に、ユーザー インターフェイスは、ユーザー名の開始文字に基づいて結果をフィルター処理するための一連の LinkButtons と、一致するユーザーを表示する GridView コントロールで構成されます。 まず、GridView 内のすべてのユーザー アカウントを一覧表示します。 次に、手順 3 で、LinkButtons フィルターを追加します。 手順 4 では、フィルター処理された結果のページングを確認します。 手順 2 から 4 で構築されたインターフェイスは、後続のチュートリアルで使用して、特定のユーザー アカウントの管理タスクを実行します。
それでは作業を始めましょう。
手順 1: 新しい ASP.NET ページの追加
このチュートリアルと次の 2 つでは、さまざまな管理関連の機能について説明します。 これらのチュートリアル全体で調べられたトピックを実装するには、一連の ASP.NET ページが必要です。 これらのページを作成し、サイト マップを更新してみましょう。
まず、 という名前 Administration
のプロジェクトに新しいフォルダーを作成します。 次に、2 つの新しい ASP.NET ページをフォルダーに追加し、各ページをマスター ページに Site.master
リンクします。 ページに次の名前を付けます。
ManageUsers.aspx
UserInformation.aspx
また、Web サイトのルート ディレクトリに と という 2 つのページをRecoverPassword.aspx
追加しますChangePassword.aspx
。
この時点で、これら 4 つのページには、マスター ページの ContentPlaceHolders MainContent
LoginContent
ごとに 1 つずつ と という 2 つの Content コントロールが必要です。
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="LoginContent" Runat="Server">
</asp:Content>
これらのページの ContentPlaceHolder のマスター ページの既定の LoginContent
マークアップを表示します。 そのため、Content コントロールの宣言型マークアップを Content2
削除します。 その後、ページのマークアップには 1 つのコンテンツ コントロールのみを含める必要があります。
フォルダー内の Administration
ASP.NET ページは、管理ユーザーのみを対象としています。 「役割の作成と管理」チュートリアルで管理者ロールをシステムに追加しました。この 2 つのページへのアクセスをこのロールに制限します。 これを実現するには、フォルダーにファイルをAdministration
追加Web.config
し、その<authorization>
要素を構成して Administrators ロールのユーザーを許可し、他のすべてのユーザーを拒否します。
<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<allow roles="Administrators" />
<deny users="*"/>
</authorization>
</system.web>
</configuration>
この時点で、プロジェクトのソリューション エクスプローラーは図 1 に示すスクリーン ショットのようになります。
図 1: 4 つの新しいページと Web.config
ファイルが Web サイトに追加されました (クリックするとフルサイズの画像が表示されます)
最後に、サイト マップ (Web.sitemap
) を更新して、ページへのエントリを ManageUsers.aspx
含めます。 Roles チュートリアルに追加した後に <siteMapNode>
、次の XML を追加します。
<siteMapNode title="User Administration" url="~/Administration/ManageUsers.aspx"/>
サイト マップが更新された状態で、ブラウザーからサイトにアクセスします。 図 2 に示すように、左側のナビゲーションには管理チュートリアルの項目が含まれるようになりました。
図 2: サイト マップには、ユーザー管理というタイトルのノードが含まれています (クリックするとフルサイズの画像が表示されます)
手順 2: GridView 内のすべてのユーザー アカウントを一覧表示する
このチュートリアルの最終目標は、管理者が管理するユーザー アカウントを選択できる、ページングされたフィルター可能なグリッドを作成することです。 まず、GridView 内のすべての ユーザーを一覧表示します。 これが完了したら、フィルター処理とページングのインターフェイスと機能を追加します。
フォルダー内の ManageUsers.aspx
ページを Administration
開き、GridView を追加し、 を ID
に設定します UserAccounts
。 しばらくすると、 クラスGetAllUsers
の メソッドを使用して、ユーザー アカウントのセットを GridView にバインドするコードをMembership
記述します。 前のチュートリアルで説明したように、GetAllUsers メソッドは オブジェクトのMembershipUser
コレクションである オブジェクトを返MembershipUserCollection
します。 コレクション内の各MembershipUser
には、、Email
IsApproved
、などのUserName
プロパティが含まれています。
GridView に目的のユーザー アカウント情報を表示するには、GridView の AutoGenerateColumns
プロパティを False に設定し、、Email
および プロパティのUserName
場合は BoundFields を、、および Comment
プロパティには CheckBoxFields IsApproved
IsLockedOut
IsOnline
を追加します。 この構成は、コントロールの宣言型マークアップまたは [フィールド] ダイアログ ボックスを使用して適用できます。 図 3 は、[フィールドの自動生成] チェック ボックスがオフになり、BoundFields と CheckBoxFields が追加および構成された後の [フィールド] ダイアログ ボックスのスクリーン ショットを示しています。
図 3: GridView に 3 つの BoundFields と 3 つの CheckBoxFields を追加する (フルサイズの画像を表示する をクリックします)
GridView を構成した後、宣言型マークアップが次のようになっていることを確認します。
<asp:GridView ID="UserAccounts" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="UserName" HeaderText="UserName"/>
<asp:BoundField DataField="Email" HeaderText="Email" />
<asp:CheckBoxField DataField="IsApproved" HeaderText="Approved?"/>
<asp:CheckBoxField DataField="IsLockedOut" HeaderText="Locked Out?" />
<asp:CheckBoxField DataField="IsOnline" HeaderText="Online?"/>
<asp:BoundField DataField="Comment" HeaderText="Comment"/>
</Columns>
</asp:GridView>
次に、ユーザー アカウントを GridView にバインドするコードを記述する必要があります。 このタスクを実行する という名前 BindUserAccounts
のメソッドを作成し、最初のページアクセス時に Page_Load
イベント ハンドラーから呼び出します。
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
BindUserAccounts();
}
private void BindUserAccounts()
{
UserAccounts.DataSource = Membership.GetAllUsers();
UserAccounts.DataBind();
}
ブラウザーを使用してページをテストします。 図 4 に示すように、 UserAccounts
GridView には、システム内のすべてのユーザーのユーザー名、電子メール アドレス、およびその他の関連するアカウント情報が一覧表示されます。
図 4: ユーザー アカウントが GridView に表示される (クリックするとフルサイズの画像が表示されます)
手順 3: ユーザー名の最初の文字で結果をフィルター処理する
現在、 UserAccounts
GridView にはすべての ユーザー アカウントが表示されます。 数百または数千のユーザー アカウントを持つ Web サイトの場合、ユーザーが表示されているアカウントを迅速に削減できることが不可欠です。 これを行うには、ページにフィルター処理 LinkButtons を追加します。 27 個の LinkButton をページに追加します。1 つは All というタイトルで、アルファベットの各文字に対して 1 つの LinkButton を追加します。 訪問者が [すべての LinkButton] をクリックすると、GridView にすべてのユーザーが表示されます。 特定の文字をクリックすると、選択した文字で始まるユーザー名を持つユーザーのみが表示されます。
最初のタスクは、27 個の LinkButton コントロールを追加することです。 1 つのオプションとして、27 LinkButtons を宣言的に 1 つずつ作成する方法があります。 より柔軟な方法は、 で Repeater コントロール ItemTemplate
を使用し、LinkButton をレンダリングし、フィルター オプションを配列として string
Repeater にバインドすることです。
まず、GridView の上のページに Repeater コントロールを UserAccounts
追加します。 Repeater の プロパティを ID
に設定します FilteringUI
。 Repeater のテンプレートを構成して、プロパティItemTemplate
と CommandName
プロパティが現在の配列要素にバインドされている LinkButton Text
をレンダリングします。 「ユーザーへのロールの 割り当て 」チュートリアルで説明したように、これはデータ バインド構文を Container.DataItem
使用して実現できます。 各リンク間に垂直線を表示するには、Repeater を SeparatorTemplate
使用します。
<asp:Repeater ID="FilteringUI" runat="server">
<ItemTemplate>
<asp:LinkButton runat="server" ID="lnkFilter"
Text='<%# Container.DataItem %>'
CommandName='<%# Container.DataItem %>'></asp:LinkButton>
</ItemTemplate>
<SeparatorTemplate>|</SeparatorTemplate>
</asp:Repeater>
この Repeater に目的のフィルター オプションを設定するには、 という名前 BindFilteringUI
のメソッドを作成します。 最初のページの読み込み時に、 Page_Load
イベント ハンドラーからこのメソッドを呼び出してください。
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
BindUserAccounts();
BindFilteringUI();
}
}
private void BindFilteringUI()
{
string[] filterOptions = { "All", "A", "B", "C","D", "E", "F", "G", "H", "I","J", "K", "L", "M", "N", "O","P", "Q", "R", "S", "T", "U","V", "W", "X", "Y", "Z" };
FilteringUI.DataSource = filterOptions;
FilteringUI.DataBind();
}
このメソッドは、配列 内の要素としてフィルターオプションを string
指定します filterOptions
。 配列内の各要素について、Repeater によって LinkButton がレンダリングされ、その Text
プロパティと CommandName
プロパティが配列要素の値に割り当てられます。
図 5 は、ブラウザーを ManageUsers.aspx
介して表示されるページを示しています。
図 5: Repeater Lists 27 Filtering LinkButtons (フルサイズの画像を表示する をクリックします)
注意
ユーザー名は、数字や句読点を含む任意の文字で始まる場合があります。 これらのアカウントを表示するには、管理者が [すべてのリンク ボタン] オプションを使用する必要があります。 または、LinkButton を追加して、数値で始まるすべてのユーザー アカウントを返すことができます。 私はこれを読者のための演習として残します。
いずれかのフィルター処理 LinkButtons をクリックするとポストバックが発生し、Repeater の ItemCommand
イベントが発生しますが、結果をフィルター処理するコードをまだ記述していないため、グリッドに変更はありません。 クラスにはMembership
、FindUsersByName
指定した検索パターンに一致するユーザー名を持つユーザー アカウントを返すメソッドが含まれています。 このメソッドを使用すると、クリックされたフィルター処理された LinkButton の で指定された文字で CommandName
始まるユーザー名を持つユーザー アカウントのみを取得できます。
まず、ページの ManageUser.aspx
分離コード クラスを更新して、 という名前 UsernameToMatch
のプロパティが含まれるようにします。 このプロパティは、ポストバック間でユーザー名フィルター文字列を保持します。
private string UsernameToMatch
{
get
{
object o = ViewState["UsernameToMatch"];
if (o == null)
return string.Empty;
else
return (string)o;
}
set
{
ViewState["UsernameToMatch"] = value;
}
}
プロパティは UsernameToMatch
、キー UsernameToMatch を使用してコレクションに ViewState
割り当てられた値を格納します。 このプロパティの値を読み取ると、コレクション内 ViewState
に値が存在するかどうかを確認します。存在しない場合は、既定値の空の文字列を返します。 プロパティは UsernameToMatch
一般的なパターンを示します。つまり、プロパティに対する変更がポストバック間で保持されるように、状態を表示する値を保持します。 このパターンの詳細については、「 ビューステート ASP.NET 理解する」を参照してください。
次に、 メソッドを更新して、 をBindUserAccounts
呼び出す代わりに を呼び出Membership.GetAllUsers
Membership.FindUsersByName
し、SQL ワイルドカード文字 %. を付加したプロパティのUsernameToMatch
値を渡します。
private void BindUserAccounts()
{
UserAccounts.DataSource = Membership.FindUsersByName(this.UsernameToMatch + "%");
UserAccounts.DataBind();
}
ユーザー名が文字 A で始まるユーザーのみを表示するには、 プロパティを UsernameToMatch
A に設定し、 を呼び出 BindUserAccounts
します。 これにより、 がMembership.FindUsersByName("A%")
呼び出され、ユーザー名が A で始まるすべてのユーザーが返されます。同様に、すべてのユーザーを返すには、空の文字列を プロパティBindUserAccounts
にUsernameToMatch
割り当てて、メソッドが を呼び出Membership.FindUsersByName("%")
すようにします。これにより、すべてのユーザー アカウントが返されます。
Repeater のイベントのイベント ハンドラーを ItemCommand
作成します。 このイベントは、いずれかのフィルター LinkButtons がクリックされるたびに発生します。クリックした LinkButton の CommandName
値が オブジェクトを RepeaterCommandEventArgs
介して渡されます。 適切な値 UsernameToMatch
を プロパティに割り当ててから、 メソッドを BindUserAccounts
呼び出す必要があります。 が All の CommandName
場合は、すべてのユーザー アカウントが表示されるように、空の文字列を に UsernameToMatch
割り当てます。 それ以外の場合は、 に値UsernameToMatch
をCommandName
割り当てます。
protected void FilteringUI_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "All")
this.UsernameToMatch = string.Empty;
else
this.UsernameToMatch e.CommandName;
BindUserAccounts();
}
このコードを配置して、フィルター機能をテストします。 ページに初めてアクセスすると、すべてのユーザー アカウントが表示されます (図 5 を参照)。 A LinkButton をクリックするとポストバックが発生し、結果がフィルター処理され、A で始まるユーザー アカウントのみが表示されます。
図 6: Filtering LinkButtons を使用して、ユーザー名が特定の文字で始まるユーザーを表示する (クリックするとフルサイズの画像が表示されます)
手順 4: ページングを使用するように GridView を更新する
図 5 と図 6 に示す GridView には、 メソッドから返されるすべてのレコードが FindUsersByName
一覧表示されます。 数百または数千のユーザー アカウントがある場合、すべてのアカウントを表示するときに情報の過負荷が発生する可能性があります (All LinkButton をクリックしたときや最初にページにアクセスしたときと同様)。 ユーザー アカウントをより管理しやすいチャンクで表示できるように、一度に 10 個のユーザー アカウントを表示するように GridView を構成しましょう。
GridView コントロールには、次の 2 種類のページングが用意されています。
- 既定のページング - 実装は簡単ですが、非効率的です。 簡単に言うと、既定のページングでは、GridView はデータ ソース からのすべての レコードを受け取ります。 その後、レコードの適切なページのみが表示されます。
- カスタム ページング - 実装にはより多くの作業が必要ですが、カスタム ページングでは、データ ソースは表示する正確なレコードセットのみを返すので、既定のページングよりも効率的です。
既定のページングとカスタム ページングのパフォーマンスの違いは、何千ものレコードをページングする場合に非常に大きな可能性があります。 このインターフェイスは、数百または数千のユーザー アカウントが存在する可能性があることを前提として構築しているため、カスタム ページングを使用しましょう。
注意
既定のページングとカスタム ページングの違い、およびカスタム ページングの実装に伴う課題の詳細については、「 大量のデータを効率的にページングする」を参照してください。
カスタム ページングを実装するには、まず、GridView によって表示されるレコードの正確なサブセットを取得するためのメカニズムが必要です。 良いニュースは、 Membership
クラスの FindUsersByName
メソッドには、ページ インデックスとページ サイズを指定できるオーバーロードがあり、そのレコードの範囲内にあるユーザー アカウントのみを返すという点です。
特に、このオーバーロードのシグネチャは です。 FindUsersByName(usernameToMatch, pageIndex, pageSize, totalRecords)
pageIndex パラメーターは、返すユーザー アカウントのページを指定します。pageSize は、ページごとに表示するレコードの数を示します。 totalRecords パラメーターは、out
ユーザー ストア内のユーザー アカウントの合計数を返すパラメーターです。
注意
によって FindUsersByName
返されるデータはユーザー名で並べ替えられます。並べ替え条件をカスタマイズすることはできません。
GridView は、ObjectDataSource コントロールにバインドされている場合にのみ、カスタム ページングを利用するように構成できます。 ObjectDataSource コントロールでカスタム ページングを実装するには、開始行インデックスと表示するレコードの最大数を渡し、そのスパン内にあるレコードの正確なサブセットを返す 2 つのメソッドが必要です。および ページングされるレコードの合計数を返す メソッド。 オーバーロードは FindUsersByName
、ページ インデックスとページ サイズを受け取り、パラメーターを使用してレコードの合計数を out
返します。 そのため、ここではインターフェイスの不一致があります。
1 つのオプションは、ObjectDataSource が期待するインターフェイスを公開するプロキシ クラスを作成し、内部的に メソッドを FindUsersByName
呼び出す方法です。 もう 1 つのオプション (およびこの記事で使用するオプション) は、独自のページング インターフェイスを作成し、GridView の組み込みページング インターフェイスの代わりに使用することです。
最初、前、次、最後のページング インターフェイスの作成
First、Previous、Next、Last LinkButtons を使用してページング インターフェイスを構築しましょう。 First LinkButton をクリックすると、ユーザーはデータの最初のページに移動しますが、Previous は前のページに戻ります。 同様に、[次へ] と [最後] は、それぞれユーザーを次のページと最後のページに移動します。 GridView の下に 4 つの LinkButton コントロールを UserAccounts
追加します。
<p>
<asp:LinkButton ID="lnkFirst" runat="server"> First</asp:LinkButton> |
<asp:LinkButton ID="lnkPrev" runat="server"> Prev</asp:LinkButton>|
<asp:LinkButton ID="lnkNext" runat="server">Next </asp:LinkButton>|
<asp:LinkButton ID="lnkLast" runat="server">Last </asp:LinkButton>
</p>
次に、LinkButton Click
の各イベントのイベント ハンドラーを作成します。
図 7 は、Visual Web Developer Design ビューで表示される 4 つの LinkButtons を示しています。
図 7: GridView の下に最初、前、次、および最後の LinkButtons を追加する (フルサイズの画像を表示する をクリックします)
現在のページ インデックスを追跡する
ユーザーが最初にページに ManageUsers.aspx
アクセスしたとき、またはいずれかのフィルター ボタンをクリックすると、GridView にデータの最初のページが表示されます。 ただし、ユーザーがいずれかのナビゲーション LinkButtons をクリックすると、ページ インデックスを更新する必要があります。 ページ インデックスとページごとに表示するレコードの数を維持するには、ページの分離コード クラスに次の 2 つのプロパティを追加します。
private int PageIndex
{
get
{
object o = ViewState["PageIndex"];
if (o == null)
return 0;
else
return (int)o;
}
set
{
ViewState["PageIndex"] = value;
}
}
private int PageSize
{
get
{
return 10;
}
}
プロパティと同様に UsernameToMatch
、 プロパティは PageIndex
値を保持して状態を表示します。 読み取り専用 PageSize
プロパティは、ハードコーディングされた値 10 を返します。 関心のあるリーダーに、このプロパティを更新して と同じパターン PageIndex
を使用し、ページにアクセスするユーザーがページごとに表示するユーザー アカウントの数を指定できるようにページを拡張 ManageUsers.aspx
するよう招待します。
現在のページのレコードの取得、ページ インデックスの更新、ページング インターフェイス LinkButtons の有効化と無効化
ページング インターフェイスを配置し、 プロパティと プロパティをPageIndex
追加することで、適切なFindUsersByName
オーバーロードをBindUserAccounts
使用するように メソッドを更新する準備PageSize
ができました。 さらに、表示されているページに応じて、このメソッドでページング インターフェイスを有効または無効にする必要があります。 データの最初のページを表示する場合は、最初と前のリンクを無効にする必要があります。最後のページを表示するときは、[次へ] と [最後] を無効にする必要があります。
BindUserAccounts
メソッドを次のコードで更新します。
private void BindUserAccounts()
{
int totalRecords;
UserAccounts.DataSource = Membership.FindUsersByName(this.UsernameToMatch + "%",this.PageIndex, this.PageSize, out totalRecords);
UserAccounts.DataBind();
// Enable/disable the paging interface
bool visitingFirstPage = (this.PageIndex == 0);
lnkFirst.Enabled = !visitingFirstPage;
lnkPrev.Enabled = !visitingFirstPage;
int lastPageIndex = (totalRecords - 1) / this.PageSize;
bool visitingLastPage = (this.PageIndex >= lastPageIndex);
lnkNext.Enabled = !visitingLastPage;
lnkLast.Enabled = !visitingLastPage;
}
ページングされるレコードの合計数は、 メソッドの最後の FindUsersByName
パラメーターによって決定されることに注意してください。 これはout
パラメーターであるため、最初に変数を宣言してこの値 (totalRecords
) を保持し、その前に キーワード (keyword)をout
付ける必要があります。
ユーザー アカウントの指定したページが返されると、データの最初のページと最後のページのどちらを表示しているかに応じて、4 つの LinkButton が有効または無効になります。
最後の手順では、4 つの LinkButtons Click
のイベント ハンドラーのコードを記述します。 これらのイベント ハンドラーでは、 プロパティを PageIndex
更新し、 の呼び出しを使用してデータを GridView に再バインドする BindUserAccounts
必要があります。 First、Previous、Next の各イベント ハンドラーは非常に単純です。 Click
ただし、Last LinkButton のイベント ハンドラーは、最後のページ インデックスを決定するために表示されるレコードの数を決定する必要があるため、もう少し複雑です。
protected void lnkFirst_Click(object sender, EventArgs e)
{
this.PageIndex = 0;
BindUserAccounts();
}
protected void lnkPrev_Click(object sender, EventArgs e)
{
this.PageIndex -= 1;
BindUserAccounts();
}
protected void lnkNext_Click(object sender, EventArgs e)
{
this.PageIndex += 1;
BindUserAccounts();
}
protected void lnkLast_Click(object sender, EventArgs e)
{
// Determine the total number of records
int totalRecords;
Membership.FindUsersByName(this.UsernameToMatch + "%", this.PageIndex,this.PageSize, out totalRecords);
// Navigate to the last page index
this.PageIndex = (totalRecords - 1) / this.PageSize;
BindUserAccounts();
}
図 8 と図 9 は、動作中のカスタム ページング インターフェイスを示しています。 図 8 は、すべてのユーザー アカウントの ManageUsers.aspx
データの最初のページを表示するときのページを示しています。 13 個のアカウントのうち 10 個のみが表示されることに注意してください。 [次へ] または [最後] リンクをクリックすると、ポストバックが発生し、 が 1 に更新 PageIndex
され、ユーザー アカウントの 2 ページ目がグリッドにバインドされます (図 9 を参照)。
図 8: 最初の 10 個のユーザー アカウントが表示されます (フルサイズの画像を表示する場合はクリックします)
図 9: [次へ] リンクをクリックすると、ユーザー アカウントの 2 ページ目が表示されます (クリックするとフルサイズの画像が表示されます)
まとめ
管理者は、多くの場合、アカウントの一覧からユーザーを選択する必要があります。 前のチュートリアルでは、ユーザーが入力されたドロップダウン リストを使用して確認しましたが、この方法はうまくスケーリングされません。 このチュートリアルでは、ページ化された GridView に結果を表示するフィルター可能なインターフェイスという、より優れた代替手段について説明しました。 このユーザー インターフェイスを使用すると、管理者は数千人の中から 1 つのユーザー アカウントをすばやく効率的に見つけて選択できます。
プログラミングに満足!
もっと読む
このチュートリアルで説明するトピックの詳細については、次のリソースを参照してください。
著者について
複数の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 Scott は、 または mitchell@4guysfromrolla.com のブログから http://ScottOnWriting.NETアクセスできます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Alicja Maziarz でした。 今後の MSDN の記事を確認することに関心がありますか? もしそうなら、私に行を落としてください mitchell@4GuysFromRolla.com
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示