メンバーシップと管理

作成者 : Erik Reitan

このチュートリアル シリーズでは、ASP.NET 4.5 と Microsoft Visual Studio Express 2013 for Web を使用して ASP.NET Web Forms アプリケーションを構築する基本について説明します。 C# ソース コードを含むVisual Studio 2013 プロジェクトは、このチュートリアル シリーズに付属しています。

このチュートリアルでは、Wingtip Toys サンプル アプリケーションを更新してカスタム ロールを追加し、id ASP.NET 使用する方法について説明します。 また、カスタム ロールを持つユーザーが Web サイトに製品を追加および削除できる管理ページを実装する方法についても説明します。

ASP.NET ID は、web アプリケーション ASP.NET ビルドするために使用されるメンバーシップ システムであり、ASP.NET 4.5 で使用できます。 ASP.NET ID は、Visual Studio 2013 Web Forms プロジェクト テンプレートと、ASP.NET MVCASP.NET Web API、ASP.NET シングル ページ アプリケーション用のテンプレートで使用されます。 また、空の Web アプリケーションで開始するときに、NuGet を使用して ASP.NET ID システムを具体的にインストールすることもできます。 ただし、このチュートリアル シリーズでは、ASP.NET ID システムを含む Web Forms projecttemplate を使用します。 ASP.NET ID を使用すると、ユーザー固有のプロファイル データをアプリケーション データと簡単に統合できます。 また、ASP.NET ID を使用すると、アプリケーション内のユーザー プロファイルの永続化モデルを選択できます。 データは、SQL Server データベースまたは Windows Azure Storage テーブルなどの NoSQL データ ストアを含む別のデータ ストアに格納できます。

このチュートリアルは、Wingtip Toys チュートリアル シリーズの「PayPal でのチェックアウトと支払い」というタイトルの前のチュートリアルに基づいています。

ここでは、次の内容について学習します。

  • コードを使用してカスタム ロールとユーザーをアプリケーションに追加する方法。
  • 管理フォルダーとページへのアクセスを制限する方法。
  • カスタム ロールに属するユーザーのナビゲーションを提供する方法。
  • モデル バインドを使用して 、DropDownList コントロールに製品カテゴリを設定する方法。
  • FileUpload コントロールを使用して Web アプリケーションにファイルをアップロードする方法。
  • 検証コントロールを使用して入力検証を実装する方法。
  • アプリケーションから製品を追加および削除する方法。

これらの機能は、チュートリアルに含まれています。

  • ASP.NET Identity
  • 構成と承認
  • モデル バインド
  • 目立たない検証

ASP.NET Web Formsでは、メンバーシップ機能が提供されます。 既定のテンプレートを使用すると、アプリケーションの実行時にすぐに使用できる組み込みのメンバーシップ機能が用意されています。 このチュートリアルでは、ASP.NET ID を使用してカスタム ロールを追加し、そのロールにユーザーを割り当てる方法について説明します。 管理フォルダーへのアクセスを制限する方法について説明します。 カスタム ロールを持つユーザーが製品を追加および削除したり、追加後に製品をプレビューしたりできるページを管理フォルダーに追加します。

カスタム ロールの追加

ASP.NET ID を使用すると、カスタム ロールを追加し、コードを使用してそのロールにユーザーを割り当てることができます。

  1. ソリューション エクスプローラーで、Logic フォルダーを右クリックし、新しいクラスを作成します。

  2. 新しいクラスに RoleActions.cs という名前を付けます

  3. 次のように表示されるようにコードを変更します。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WingtipToys.Logic
    {
        internal class RoleActions
        {
        }
    }
    
  4. ソリューション エクスプローラーGlobal.asax.cs ファイルを開きます。

  5. 次のように黄色で強調表示されたコードを追加して、 Global.asax.cs ファイルを変更します。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Optimization;
    using System.Web.Routing;
    using System.Web.Security;
    using System.Web.SessionState;
    using System.Data.Entity;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
        public class Global : HttpApplication
        {
            void Application_Start(object sender, EventArgs e)
            {
              // Code that runs on application startup
              RouteConfig.RegisterRoutes(RouteTable.Routes);
              BundleConfig.RegisterBundles(BundleTable.Bundles);
    
              // Initialize the product database.
              Database.SetInitializer(new ProductDatabaseInitializer());
    
              // Create the custom role and user.
              RoleActions roleActions = new RoleActions();
              roleActions.AddUserAndRole();
            }
        }
    }
    
  6. AddUserAndRole は赤色の下線付きになっています。 AddUserAndRole コードをダブルクリックします。
    強調表示されたメソッドの先頭にある文字 "A" に下線が引きます。

  7. 文字 "A" の上にカーソルを合わせ、メソッドのメソッド スタブ AddUserAndRole を生成できる UI をクリックします。

    メンバーシップと管理 - メソッド スタブの生成

  8. 次のタイトルのオプションをクリックします。
    Generate method stub for "AddUserAndRole" in "WingtipToys.Logic.RoleActions"

  9. Logic フォルダーから RoleActions.cs ファイルを開きます。
    AddUserAndRoleメソッドがクラス ファイルに追加されました。

  10. RoleActions.cs ファイルを変更します。次のように表示されるように、 をNotImplementedException削除し、黄色で強調表示されたコードを追加します。

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.EntityFramework;
    
    namespace WingtipToys.Logic
    {
      internal class RoleActions
      {
        internal void AddUserAndRole()
        {
          // Access the application context and create result variables.
          Models.ApplicationDbContext context = new ApplicationDbContext();
          IdentityResult IdRoleResult;
          IdentityResult IdUserResult;
    
          // Create a RoleStore object by using the ApplicationDbContext object. 
          // The RoleStore is only allowed to contain IdentityRole objects.
          var roleStore = new RoleStore<IdentityRole>(context);
    
          // Create a RoleManager object that is only allowed to contain IdentityRole objects.
          // When creating the RoleManager object, you pass in (as a parameter) a new RoleStore object. 
          var roleMgr = new RoleManager<IdentityRole>(roleStore);
    
          // Then, you create the "canEdit" role if it doesn't already exist.
          if (!roleMgr.RoleExists("canEdit"))
          {
            IdRoleResult = roleMgr.Create(new IdentityRole { Name = "canEdit" });
          }
    
          // Create a UserManager object based on the UserStore object and the ApplicationDbContext  
          // object. Note that you can create new objects and use them as parameters in
          // a single line of code, rather than using multiple lines of code, as you did
          // for the RoleManager object.
          var userMgr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
          var appUser = new ApplicationUser
          {
            UserName = "canEditUser@wingtiptoys.com",
            Email = "canEditUser@wingtiptoys.com"
          };
          IdUserResult = userMgr.Create(appUser, ConfigurationManager.AppSettings["AppUserPasswordKey"]);
    
          // If the new "canEdit" user was successfully created, 
          // add the "canEdit" user to the "canEdit" role. 
          if (!userMgr.IsInRole(userMgr.FindByEmail("canEditUser@wingtiptoys.com").Id, "canEdit"))
          {
            IdUserResult = userMgr.AddToRole(userMgr.FindByEmail("canEditUser@wingtiptoys.com").Id, "canEdit");
          }
        }
      }
    }
    

上記のコードでは、まずメンバーシップ データベースのデータベース コンテキストを確立します。 メンバーシップ データベースは、App_Data フォルダーの .mdf ファイルとしても格納されます。 最初のユーザーがこの Web アプリケーションにサインインすると、このデータベースを表示できます。

Note

メンバーシップ データと製品データを格納する場合は、上記のコードで製品データを格納するために使用したものと同じ DbContext の使用を検討できます。

内部キーワード (keyword)は、型 (クラスなど) および型メンバー (メソッドやプロパティなど) のアクセス修飾子です。 内部型またはメンバーには、同じアセンブリ (.dll ファイル) に含まれるファイル内でのみアクセスできます。 アプリケーションをビルドすると、アプリケーションの実行時に実行されるコードを含むアセンブリ ファイル (.dll) が作成されます。

RoleStoreロール管理を提供する オブジェクトは、データベース コンテキストに基づいて作成されます。

Note

オブジェクトが RoleStore 作成されると、ジェネリック IdentityRole 型が使用されます。 つまり、 RoleStore にはオブジェクトのみを含 IdentityRole める必要があります。 また、ジェネリックを使用することで、メモリ内のリソースをより適切に処理できます。

次に、 RoleManager オブジェクトは、先ほど作成した RoleStore オブジェクトに基づいて作成されます。 オブジェクトは RoleManager 、ロールに関連する API を公開します。これは、 への変更を自動的に RoleStore保存するために使用できます。 RoleManagerコードではジェネリック型を使用<IdentityRole>するため、 にはオブジェクトのみを含IdentityRoleめる必要があります。

メソッドを RoleExists 呼び出して、"canEdit" ロールがメンバーシップ データベースに存在するかどうかを判断します。 そうでない場合は、ロールを作成します。

オブジェクトの UserManager 作成はコントロールよりも RoleManager 複雑に見えますが、ほぼ同じです。 これは、複数行ではなく 1 行にコーディングされています。 ここでは、渡すパラメーターがかっこに含まれる新しいオブジェクトとしてインスタンス化されます。

次に、新しい ApplicationUser オブジェクトを作成して "canEditUser" ユーザーを作成します。 次に、ユーザーを正常に作成した場合は、新しいロールにユーザーを追加します。

Note

エラー処理は、このチュートリアル シリーズの後半の「ASP.NET エラー処理」チュートリアルで更新されます。

次にアプリケーションを起動すると、"canEditUser" という名前のユーザーが、アプリケーションの "canEdit" という名前のロールとして追加されます。 このチュートリアルの後半では、"canEditUser" ユーザーとしてログインして、このチュートリアルで追加する追加機能を表示します。 ASP.NET ID に関する API の詳細については、「 Microsoft.AspNet.Identity 名前空間」を参照してください。 ASP.NET ID システムの初期化の詳細については、 AspnetIdentitySample を参照してください。

管理ページへのアクセスの制限

Wingtip Toys サンプル アプリケーションを使用すると、匿名ユーザーとログイン ユーザーの両方が製品を表示および購入できます。 ただし、カスタムの "canEdit" ロールを持つログイン ユーザーは、製品を追加および削除するために制限付きページにアクセスできます。

管理フォルダーとページを追加する

次に、Wingtip Toys サンプル アプリケーションのカスタム ロールに属する "canEditUser" ユーザーの管理という名前のフォルダーを作成します。

  1. ソリューション エクスプローラーでプロジェクト名 (Wingtip Toys) を右クリックし、[追加] ->[新しいフォルダー] を選択します。
  2. 新しいフォルダーに管理という名前を付けます。
  3. 管理 フォルダーを右クリックし、[追加] ->[新しい項目] を選択します。
    [新しい項目の追加] ダイアログ ボックスが表示されます。
  4. 左側の [Visual C#->Web テンプレート] グループを選択します。 中央の一覧から [マスター ページを含む Web フォーム] を選択し、AdminPage.aspx という名前を付けて、[追加] を選択します。
  5. マスター ページとして Site.Master ファイルを選択し、[ OK] を選択します

Web.config ファイルを追加する

Web.config ファイルを 管理 フォルダーに追加することで、フォルダーに含まれるページへのアクセスを制限できます。

  1. 管理 フォルダーを右クリックし、[追加] ->[新しい項目] の順に選択します。
    [新しい項目の追加] ダイアログ ボックスが表示されます。

  2. Visual C# Web テンプレートの一覧から、中央の一覧から [Web 構成ファイル] を選択し、既定の名前Web.config受け入れて、[追加] を選択します。

  3. Web.config ファイルの XML の内容を次の内容で置き換えます。

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <authorization>
          <allow roles="canEdit"/>
          <deny users="*"/>
        </authorization>
      </system.web>
    </configuration>
    

Web.config ファイルを保存します。 Web.config ファイルは、アプリケーションの "canEdit" ロールに属するユーザーのみが、管理 フォルダーに含まれるページにアクセスできることを指定します。

カスタム ロール ナビゲーションを含む

カスタム "canEdit" ロールのユーザーがアプリケーションの管理セクションに移動できるようにするには、 Site.Master ページへのリンクを追加する必要があります。 "canEdit" ロールに属するユーザーのみが、管理リンクを表示し、管理セクションにアクセスできます。

  1. ソリューション エクスプローラーで、Site.Master ページを見つけて開きます。

  2. "canEdit" ロールのユーザーのリンクを作成するには、黄色で強調表示されたマークアップを次の順序なしのリスト <ul> 要素に追加して、リストが次のように表示されるようにします。

    <ul class="nav navbar-nav">
        <li><a runat="server" id="adminLink" visible="false" 
          href="~/Admin/AdminPage">Admin</a></li>
        <li><a runat="server" href="~/">Home</a></li>
        <li><a runat="server" href="~/About">About</a></li>
        <li><a runat="server" href="~/Contact">Contact</a></li>
        <li><a runat="server" href="~/ProductList">Products</a></li>
        <li><a runat="server" href="~/ShoppingCart" 
          ID="cartCount">&nbsp;</a></li>
    </ul>
    
  3. Site.Master.cs ファイルを開きます。 黄色で強調表示されたPage_Loadコードをハンドラーに追加して、管理 リンクを "canEditUser" ユーザーにのみ表示します。 ハンドラーは Page_Load 次のように表示されます。

    protected void Page_Load(object sender, EventArgs e)
    {
        if (HttpContext.Current.User.IsInRole("canEdit"))
        {
            adminLink.Visible = true;
        }
    }
    

ページが読み込まれると、コードは、ログインしているユーザーが "canEdit" のロールを持っているかどうかを確認します。 ユーザーが "canEdit" ロールに属している場合、 AdminPage.aspx ページへのリンクを含む span 要素 (その結果、スパン内のリンク) が表示されます。

製品管理の有効化

ここまでで、"canEdit" ロールを作成し、"canEditUser" ユーザー、管理フォルダー、および管理ページを追加しました。 管理フォルダーとページのアクセス権を設定し、"canEdit" ロールのユーザーのナビゲーション リンクをアプリケーションに追加しました。 次に、 AdminPage.aspx ページにマークアップを追加し、"canEdit" ロールを持つユーザーが製品を追加および削除できるようにする AdminPage.aspx.cs 分離コード ファイルにコードを追加します。

  1. ソリューション エクスプローラーで、管理 フォルダーから AdminPage.aspx ファイルを開きます。

  2. 既存のマークアップを次のように置き換えます。

    <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="AdminPage.aspx.cs" Inherits="WingtipToys.Admin.AdminPage" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <h1>Administration</h1>
        <hr />
        <h3>Add Product:</h3>
        <table>
            <tr>
                <td><asp:Label ID="LabelAddCategory" runat="server">Category:</asp:Label></td>
                <td>
                    <asp:DropDownList ID="DropDownAddCategory" runat="server" 
                        ItemType="WingtipToys.Models.Category" 
                        SelectMethod="GetCategories" DataTextField="CategoryName" 
                        DataValueField="CategoryID" >
                    </asp:DropDownList>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddName" runat="server">Name:</asp:Label></td>
                <td>
                    <asp:TextBox ID="AddProductName" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" Text="* Product name required." ControlToValidate="AddProductName" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddDescription" runat="server">Description:</asp:Label></td>
                <td>
                    <asp:TextBox ID="AddProductDescription" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" Text="* Description required." ControlToValidate="AddProductDescription" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddPrice" runat="server">Price:</asp:Label></td>
                <td>
                    <asp:TextBox ID="AddProductPrice" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" Text="* Price required." ControlToValidate="AddProductPrice" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                    <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" Text="* Must be a valid price without $." ControlToValidate="AddProductPrice" SetFocusOnError="True" Display="Dynamic" ValidationExpression="^[0-9]*(\.)?[0-9]?[0-9]?$"></asp:RegularExpressionValidator>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddImageFile" runat="server">Image File:</asp:Label></td>
                <td>
                    <asp:FileUpload ID="ProductImage" runat="server" />
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" Text="* Image path required." ControlToValidate="ProductImage" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                </td>
            </tr>
        </table>
        <p></p>
        <p></p>
        <asp:Button ID="AddProductButton" runat="server" Text="Add Product" OnClick="AddProductButton_Click"  CausesValidation="true"/>
        <asp:Label ID="LabelAddStatus" runat="server" Text=""></asp:Label>
        <p></p>
        <h3>Remove Product:</h3>
        <table>
            <tr>
                <td><asp:Label ID="LabelRemoveProduct" runat="server">Product:</asp:Label></td>
                <td><asp:DropDownList ID="DropDownRemoveProduct" runat="server" ItemType="WingtipToys.Models.Product" 
                        SelectMethod="GetProducts" AppendDataBoundItems="true" 
                        DataTextField="ProductName" DataValueField="ProductID" >
                    </asp:DropDownList>
                </td>
            </tr>
        </table>
        <p></p>
        <asp:Button ID="RemoveProductButton" runat="server" Text="Remove Product" OnClick="RemoveProductButton_Click" CausesValidation="false"/>
        <asp:Label ID="LabelRemoveStatus" runat="server" Text=""></asp:Label>
    </asp:Content>
    
  3. 次に、 AdminPage.aspx.cs 分離コード ファイルを開きます。次に、 AdminPage.aspx を右クリックし、[ コードの表示] をクリックします。

  4. AdminPage.aspx.cs 分離コード ファイル内の既存のコードを次のコードに置き換えます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys.Admin
    {
      public partial class AdminPage : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          string productAction = Request.QueryString["ProductAction"];
          if (productAction == "add")
          {
            LabelAddStatus.Text = "Product added!";
          }
    
          if (productAction == "remove")
          {
            LabelRemoveStatus.Text = "Product removed!";
          }
        }
    
        protected void AddProductButton_Click(object sender, EventArgs e)
        {
          Boolean fileOK = false;
          String path = Server.MapPath("~/Catalog/Images/");
          if (ProductImage.HasFile)
          {
            String fileExtension = System.IO.Path.GetExtension(ProductImage.FileName).ToLower();
            String[] allowedExtensions = { ".gif", ".png", ".jpeg", ".jpg" };
            for (int i = 0; i < allowedExtensions.Length; i++)
            {
              if (fileExtension == allowedExtensions[i])
              {
                fileOK = true;
              }
            }
          }
    
          if (fileOK)
          {
            try
            {
              // Save to Images folder.
              ProductImage.PostedFile.SaveAs(path + ProductImage.FileName);
              // Save to Images/Thumbs folder.
              ProductImage.PostedFile.SaveAs(path + "Thumbs/" + ProductImage.FileName);
            }
            catch (Exception ex)
            {
              LabelAddStatus.Text = ex.Message;
            }
    
            // Add product data to DB.
            AddProducts products = new AddProducts();
            bool addSuccess = products.AddProduct(AddProductName.Text, AddProductDescription.Text,
                AddProductPrice.Text, DropDownAddCategory.SelectedValue, ProductImage.FileName);
            if (addSuccess)
            {
              // Reload the page.
              string pageUrl = Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.Count() - Request.Url.Query.Count());
              Response.Redirect(pageUrl + "?ProductAction=add");
            }
            else
            {
              LabelAddStatus.Text = "Unable to add new product to database.";
            }
          }
          else
          {
            LabelAddStatus.Text = "Unable to accept file type.";
          }
        }
    
        public IQueryable GetCategories()
        {
          var _db = new WingtipToys.Models.ProductContext();
          IQueryable query = _db.Categories;
          return query;
        }
    
        public IQueryable GetProducts()
        {
          var _db = new WingtipToys.Models.ProductContext();
          IQueryable query = _db.Products;
          return query;
        }
    
        protected void RemoveProductButton_Click(object sender, EventArgs e)
        {
          using (var _db = new WingtipToys.Models.ProductContext())
          {
            int productId = Convert.ToInt16(DropDownRemoveProduct.SelectedValue);
            var myItem = (from c in _db.Products where c.ProductID == productId select c).FirstOrDefault();
            if (myItem != null)
            {
              _db.Products.Remove(myItem);
              _db.SaveChanges();
    
              // Reload the page.
              string pageUrl = Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.Count() - Request.Url.Query.Count());
              Response.Redirect(pageUrl + "?ProductAction=remove");
            }
            else
            {
              LabelRemoveStatus.Text = "Unable to locate product.";
            }
          }
        }
      }
    }
    

AdminPage.aspx.cs 分離コード ファイルに入力したコードでは、 というAddProductsクラスが、データベースに製品を追加する実際の作業を行います。 このクラスはまだ存在しないため、ここで作成します。

  1. ソリューション エクスプローラーで、[ロジック] フォルダーを右クリックし、[追加] ->[新しい項目] の順に選択します。
    [新しい項目の追加] ダイアログ ボックスが表示されます。

  2. 左側の [Visual C# ->Code templates] グループを選択します。 次に、中央の一覧から [ クラス] を選択し、 AddProducts.cs という名前を付けます
    新しいクラス ファイルが表示されます。

  3. 既存のコードを次のコードに置き換えます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    
    namespace WingtipToys.Logic
    {
        public class AddProducts
        {
            public bool AddProduct(string ProductName, string ProductDesc, string ProductPrice, string ProductCategory, string ProductImagePath)
            {
                var myProduct = new Product();
                myProduct.ProductName = ProductName;
                myProduct.Description = ProductDesc;
                myProduct.UnitPrice = Convert.ToDouble(ProductPrice);
                myProduct.ImagePath = ProductImagePath;
                myProduct.CategoryID = Convert.ToInt32(ProductCategory);
    
                using (ProductContext _db = new ProductContext())
                {
                    // Add product to DB.
                    _db.Products.Add(myProduct);
                    _db.SaveChanges();
                }
                // Success.
                return true;
            }
        }
    }
    

AdminPage.aspx ページでは、"canEdit" ロールに属するユーザーが製品を追加および削除できます。 新しい製品が追加されると、製品に関する詳細が検証され、データベースに入力されます。 新しい製品は、Web アプリケーションのすべてのユーザーがすぐに使用できます。

目立たない検証

ユーザーが AdminPage.aspx ページで提供する製品の詳細は、検証コントロール (RequiredFieldValidatorRegularExpressionValidator) を使用して検証されます。 これらのコントロールでは、目立たない検証が自動的に使用されます。 控えめな検証により、検証コントロールはクライアント側の検証ロジックに JavaScript を使用できます。つまり、ページでサーバーへの移動を検証する必要はありません。 既定では、次の構成設定に基づいて、目立たない検証が Web.config ファイルに含まれます。

<add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" />

[正規表現]

AdminPage.aspx ページの製品価格は、RegularExpressionValidator コントロールを使用して検証されます。 このコントロールは、関連付けられた入力コントロール ("AddProductPrice" TextBox) の値が正規表現で指定されたパターンと一致するかどうかを検証します。 正規表現は、特定の文字パターンをすばやく見つけて照合できるパターンマッチング表記です。 RegularExpressionValidator コントロールには、次に示すように、価格入力の検証に使用される正規表現を含む という名前ValidationExpressionのプロパティが含まれています。

<asp:RegularExpressionValidator 
    ID="RegularExpressionValidator1" runat="server"
    Text="* Must be a valid price without $." ControlToValidate="AddProductPrice" 
    SetFocusOnError="True" Display="Dynamic" 
    ValidationExpression="^[0-9]*(\.)?[0-9]?[0-9]?$">
</asp:RegularExpressionValidator>

FileUpload コントロール

入力コントロールと検証コントロールに加えて、 FileUpload コントロールを AdminPage.aspx ページに追加しました。 このコントロールは、ファイルをアップロードする機能を提供します。 この場合、画像ファイルのアップロードのみを許可します。 分離コード ファイル (AdminPage.aspx.cs) で、 AddProductButton をクリックすると、FileUpload コントロールの プロパティがチェックHasFileされます。 コントロールにファイルがあり、ファイルの種類 (ファイル拡張子に基づく) が許可されている場合、イメージはアプリケーションの Images フォルダーと Images/Thumbs フォルダーに保存されます。

モデル バインド

このチュートリアル シリーズの前半では、モデル バインドを使用して、ListView コントロール、FormsView コントロール、GridView コントロール、DetailView コントロールを設定しました。 このチュートリアルでは、モデル バインドを使用して、製品カテゴリの一覧を DropDownList コントロールに設定します。

AdminPage.aspx ファイルに追加したマークアップには、 という名前の DropDownList コントロールがDropDownAddCategory含まれています。

<asp:DropDownList ID="DropDownAddCategory" runat="server" 
        ItemType="WingtipToys.Models.Category" 
        SelectMethod="GetCategories" DataTextField="CategoryName" 
        DataValueField="CategoryID" >
    </asp:DropDownList>

モデル バインドを使用して、 属性と 属性を設定して、この DropDownListItemType 値を SelectMethod 設定します。 属性は ItemType 、コントロールにデータを設定するときに 型を WingtipToys.Models.Category 使用することを指定します。 このチュートリアル シリーズの最初に、 クラスを作成してこの型を Category 定義しました (以下に示します)。 クラスはCategoryCategory.cs ファイル内の Models フォルダーにあります。

public class Category
{
    [ScaffoldColumn(false)]
    public int CategoryID { get; set; }

    [Required, StringLength(100), Display(Name = "Name")]
    public string CategoryName { get; set; }

    [Display(Name = "Product Description")]
    public string Description { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

DropDownList コントロールの 属性はSelectMethod、分離コード ファイル (AdminPage.aspx.cs) に含まれるメソッド (以下に示す) を使用GetCategoriesすることを指定します。

public IQueryable GetCategories()
{
  var _db = new WingtipToys.Models.ProductContext();
  IQueryable query = _db.Categories;
  return query;
}

このメソッドは、型に対CategoryしてクエリをIQueryable評価するためにインターフェイスを使用することを指定します。 返された値は、ページのマークアップ (AdminPage.aspx) で DropDownList を設定するために使用されます。

リスト内の各項目に表示されるテキストは、 属性を DataTextField 設定して指定します。 属性はDataTextField、 クラスの をCategory使用CategoryNameして (上に示した) DropDownList コントロールの各カテゴリを表示します。 DropDownList コントロールで項目が選択されたときに渡される実際の値は、 DataValueField 属性に基づいています。 属性はDataValueField、 クラスでCategory定義されているように にCategoryID設定されます (上に示します)。

アプリケーションのしくみ

"canEdit" ロールに属するユーザーが初めてページに移動すると、DropDownAddCategory前述のように DropDownList コントロールが設定されます。 DropDownRemoveProductDropDownList コントロールには、同じアプローチを使用する製品も設定されます。 "canEdit" ロールに属するユーザーは、カテゴリの種類を選択し、製品の詳細 (名前説明価格イメージ ファイル) を追加します。 "canEdit" ロールに属するユーザーが [ 製品の追加 ] ボタンをクリックすると、 AddProductButton_Click イベント ハンドラーがトリガーされます。 分離コード ファイル (AdminPage.aspx.cs) にあるイベント ハンドラーはAddProductButton_Click、イメージ ファイルが許可されているファイルの種類 (.gif.png.jpeg、または .jpg) と一致していることを確認します。 次に、イメージ ファイルが Wingtip Toys サンプル アプリケーションのフォルダーに保存されます。 次に、新しい製品がデータベースに追加されます。 新しい製品を追加するために、 クラスの新しいインスタンスが AddProducts 作成され、products という名前が付けられます。 クラスには AddProducts という名前 AddProductのメソッドがあり、products オブジェクトはこのメソッドを呼び出して製品をデータベースに追加します。

// Add product data to DB.
AddProducts products = new AddProducts();
bool addSuccess = products.AddProduct(AddProductName.Text, AddProductDescription.Text,
    AddProductPrice.Text, DropDownAddCategory.SelectedValue, ProductImage.FileName);

コードによって新しい製品がデータベースに正常に追加された場合、ページはクエリ文字列値 ProductAction=addで再読み込みされます。

Response.Redirect(pageUrl + "?ProductAction=add");

ページが再読み込みされると、クエリ文字列が URL に含まれます。 ページを再読み込みすると、"canEdit" ロールに属するユーザーは、AdminPage.aspx ページの DropDownList コントロールの更新をすぐに確認できます。 また、URL にクエリ文字列を含めることで、"canEdit" ロールに属するユーザーに成功メッセージを表示できます。

AdminPage.aspx ページが再読み込みされると、Page_Loadイベントが呼び出されます。

protected void Page_Load(object sender, EventArgs e)
{
    string productAction = Request.QueryString["ProductAction"];
    if (productAction == "add")
    {
        LabelAddStatus.Text = "Product added!";
    }

    if (productAction == "remove")
    {
        LabelRemoveStatus.Text = "Product removed!";
    }
}

イベント ハンドラーは Page_Load 、クエリ文字列の値を確認し、成功メッセージを表示するかどうかを決定します。

アプリケーションの実行

これでアプリケーションを実行して、ショッピング カート内のアイテムを追加、削除、更新する方法を確認できます。 ショッピング カートの合計には、ショッピング カート内のすべてのアイテムの合計コストが反映されます。

  1. ソリューション エクスプローラーで、F5 キーを押して Wingtip Toys サンプル アプリケーションを実行します。
    ブラウザーが開き、 Default.aspx ページが表示されます。

  2. ページの上部にある [ ログイン ] リンクをクリックします。

    メンバーシップと管理 - ログイン リンク

    Login.aspx ページが表示されます。

  3. ユーザー名とパスワードを入力します。

    メンバーシップと管理 - [ログイン] ページ

  4. ページの下部付近にある [ ログイン ] ボタンをクリックします。

  5. 次のページの上部にある [管理] リンクを選択して、AdminPage.aspx ページに移動します。

    メンバーシップと管理 - 管理 リンク

  6. 入力検証をテストするには、製品の詳細を追加せずに [ 製品の追加 ] ボタンをクリックします。

    メンバーシップと管理 - [管理] ページ

    必須フィールド メッセージが表示されていることに注意してください。

  7. 新しい製品の詳細を追加し、[ 製品の追加 ] ボタンをクリックします。

    メンバーシップと管理 - 製品の追加

  8. 上部のナビゲーション メニューから [ 製品 ] を選択して、追加した新しい製品を表示します。

    メンバーシップと管理 - 新しい製品の表示

  9. [管理] リンクをクリックして、管理ページに戻ります。

  10. ページの [ 製品の削除 ] セクションで、 DropDownListBox に追加した新しい製品を選択します。

  11. [ 製品の削除 ] ボタンをクリックして、アプリケーションから新しい製品を削除します。

    メンバーシップと管理 - 製品の削除

  12. 上部のナビゲーション メニューから [ 製品 ] を選択して、製品が削除されたことを確認します。

  13. [ ログオフ ] をクリックして、管理モードを存在させます。
    上部のナビゲーション ウィンドウに管理メニュー項目が表示されなくなったことに注意してください。

まとめ

このチュートリアルでは、カスタム ロールとカスタム ロールに属するユーザーを追加し、管理フォルダーとページへのアクセスを制限し、カスタム ロールに属するユーザーのナビゲーションを提供しました。 モデル バインドを使用して 、DropDownList コントロールにデータを設定しました。 FileUpload コントロールと検証コントロールを実装しました。 また、データベースから製品を追加および削除する方法についても学習しました。 次のチュートリアルでは、ASP.NET ルーティングを実装する方法について説明します。

その他のリソース

Web.config - authorization 要素
ASP.NET Identity
メンバーシップ、OAuth、SQL Databaseを使用してセキュリティで保護された ASP.NET Web Forms アプリを Azure Web サイトにデプロイする
Microsoft Azure - 無料試用版