パート 6: ASP.NET メンバーシップ

作成者: Joe Stagner

Note

この記事が作成された後で、ASP.NET メンバーシップ プロバイダーは ASP.NET Identity に置き換えられました。 この記事の作成時点で紹介されているメンバーシップ プロバイダーではなく、ASP.NET Identity プラットフォームを使うようにアプリを更新することを強くお勧めします。 ASP.NET メンバーシップ システムと比べると、ASP.NET Identity には次のような多くの利点があります。

  • パフォーマンスの向上
  • 向上した拡張性とテストの容易性
  • OAuth、OpenID Connect、2 要素認証のサポート
  • クレームベースの ID のサポート
  • ASP.Net Core との相互運用性の向上

Tailspin Spyworks は、.NET プラットフォーム用の高性能でスケーラブルなアプリケーションを簡単に作成できる方法を実証します。 ASP.NET 4 の優れた新機能を使用して、ショッピング、チェックアウト、管理など、オンライン ストアを構築する方法を示します。

このチュートリアル シリーズでは、Tailspin Spyworks サンプル アプリケーションを作成するために必要なすべての手順について詳しく説明します。 パート 6 では、ASP.NET メンバーシップを追加します。

ASP.NET メンバーシップの操作

Screenshot that shows where to select A S P dot NET Configuration.

[セキュリティ] をクリックします。

Screenshot that shows where to click Security.

フォーム認証を使っていることを確認します。

Screenshot that shows how to confirm that you are using forms authentication.

[ユーザーの作成] リンクを使って、ユーザーを何人か作成します。

Screenshot that shows where to click Create User.

完了したら、ソリューション エクスプローラー ウィンドウを参照して、ビューを更新します。

Screenshot that shows where to refresh the view.

ASPNETDB.MDF ファイルが作成されていることに注意してください。 このファイルには、メンバーシップなどのコア ASP.NET サービスをサポートするテーブルが含まれています。

これで、チェックアウト プロセスの実装を始められます。

最初に、CheckOut.aspx ページを作成します。

CheckOut.aspx ページは、ログインしているユーザーのみが使用できるようにする必要があるため、ログインしているユーザーにアクセスを制限し、ログインしていないユーザーはログイン ページにリダイレクトします。

そのためには、web.config ファイルの構成セクションに以下を追加します。

<location path="Checkout.aspx">
    <system.web>
      <authorization>
        <deny users="?" />
      </authorization>
    </system.web>
  </location>

ASP.NET Web Forms アプリケーションのテンプレートによって、web.config ファイルに認証セクションが自動的に追加され、既定のログイン ページが確立されました。

<authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="2880" />
    </authentication>

ユーザーがログインしたら匿名ショッピング カートを移行するように、Login.aspx 分離コード ファイルを変更する必要があります。 Page_Load イベントを次のように変更します。

using System.Web.Security;

protected void Page_Load(object sender, EventArgs e)
{
  // If the user is not submitting their credentials
  // save refferer
  if (!Page.IsPostBack)
     {
     if (Page.Request.UrlReferrer != null)
        {
        Session["LoginReferrer"] = Page.Request.UrlReferrer.ToString();
        }
      }
           
  // User is logged in so log them out.
  if (User.Identity.IsAuthenticated)
     {
     FormsAuthentication.SignOut();
     Response.Redirect("~/");
     }
}

次に、次のような "LoggedIn" イベント ハンドラーを追加して、新しくログインしたユーザーにセッション名を設定し、MyShoppingCart クラスの MigrateCart メソッドを呼び出して、ショッピング カートの一時セッション ID をユーザーのそれに変更します。 (.cs ファイルで実装されています)

protected void LoginUser_LoggedIn(object sender, EventArgs e)
{
  MyShoppingCart usersShoppingCart = new MyShoppingCart();
  String cartId = usersShoppingCart.GetShoppingCartId();
  usersShoppingCart.MigrateCart(cartId, LoginUser.UserName);
            
  if(Session["LoginReferrer"] != null)
    {
    Response.Redirect(Session["LoginReferrer"].ToString());
    }

  Session["UserName"] = LoginUser.UserName;
}

次のような MigrateCart() メソッドを実装します。

//--------------------------------------------------------------------------------------+
public void MigrateCart(String oldCartId, String UserName)
{
  using (CommerceEntities db = new CommerceEntities())
    {
    try
      {
      var myShoppingCart = from cart in db.ShoppingCarts
                           where cart.CartID == oldCartId
                           select cart;

      foreach (ShoppingCart item in myShoppingCart)
        {
        item.CartID = UserName;                 
        }
      db.SaveChanges();
      Session[CartId] = UserName;
      }
    catch (Exception exp)
      {
      throw new Exception("ERROR: Unable to Migrate Shopping Cart - " +     
                           exp.Message.ToString(), exp);
      }
    }           
}

checkout.aspx では、ショッピング カート ページと同様に、チェックアウト ページで EntityDataSource と GridView を使います。

<div id="CheckOutHeader" runat="server" class="ContentHead">
  Review and Submit Your Order
</div>
<span id="Message" runat="server"><br />     
   <asp:Label ID="LabelCartHeader" runat="server" 
              Text="Please check all the information below to be sure it&#39;s correct.">
   </asp:Label>
</span><br /> 
<asp:GridView ID="MyList" runat="server" AutoGenerateColumns="False" 
              DataKeyNames="ProductID,UnitCost,Quantity" 
              DataSourceID="EDS_Cart" 
              CellPadding="4" GridLines="Vertical" CssClass="CartListItem" 
              onrowdatabound="MyList_RowDataBound" ShowFooter="True">
  <AlternatingRowStyle CssClass="CartListItemAlt" />
  <Columns>
    <asp:BoundField DataField="ProductID" HeaderText="Product ID" ReadOnly="True" 
                    SortExpression="ProductID"  />
    <asp:BoundField DataField="ModelNumber" HeaderText="Model Number" 
                    SortExpression="ModelNumber" />
    <asp:BoundField DataField="ModelName" HeaderText="Model Name" 
                    SortExpression="ModelName" />
    <asp:BoundField DataField="UnitCost" HeaderText="Unit Cost" ReadOnly="True" 
                    SortExpression="UnitCost" DataFormatString="{0:c}" />
    <asp:BoundField DataField="Quantity" HeaderText="Quantity" ReadOnly="True" 
                    SortExpression="Quantity" />
    <asp:TemplateField> 
      <HeaderTemplate>Item Total</HeaderTemplate>
      <ItemTemplate>
        <%# (Convert.ToDouble(Eval("Quantity")) * Convert.ToDouble(Eval("UnitCost")))%>
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
  <FooterStyle CssClass="CartListFooter"/>
  <HeaderStyle  CssClass="CartListHead" />
</asp:GridView>   
    
<br />
<asp:imagebutton id="CheckoutBtn" runat="server" ImageURL="Styles/Images/submit.gif" 
                                  onclick="CheckoutBtn_Click">
</asp:imagebutton>
<asp:EntityDataSource ID="EDS_Cart" runat="server" 
                      ConnectionString="name=CommerceEntities" 
                      DefaultContainerName="CommerceEntities" 
                      EnableFlattening="False" 
                      EnableUpdate="True" 
                      EntitySetName="ViewCarts" 
                      AutoGenerateWhereClause="True" 
                      EntityTypeFilter="" 
                      Select="" Where="">
   <WhereParameters>
      <asp:SessionParameter Name="CartID" DefaultValue="0" 
                                          SessionField="TailSpinSpyWorks_CartID" />
   </WhereParameters>
</asp:EntityDataSource>

GridView コントロールでは MyList_RowDataBound という名前の "ondatabound" イベント ハンドラーが指定されているので、次のようにそのイベント ハンドラーを実装します。

decimal _CartTotal = 0;

//--------------------------------------------------------------------------------------+
protected void MyList_RowDataBound(object sender, GridViewRowEventArgs e)
{
  if (e.Row.RowType == DataControlRowType.DataRow)
     {
     TailspinSpyworks.Data_Access.ViewCart myCart = new Data_Access.ViewCart();
     myCart = (TailspinSpyworks.Data_Access.ViewCart)e.Row.DataItem;
     _CartTotal += myCart.UnitCost * myCart.Quantity;
     }
   else if (e.Row.RowType == DataControlRowType.Footer)
     {
     if (_CartTotal > 0)
        {
        CheckOutHeader.InnerText = "Review and Submit Your Order";
        LabelCartHeader.Text = "Please check all the information below to be sure
                                                                it&#39;s correct.";
        CheckoutBtn.Visible = true;
        e.Row.Cells[5].Text = "Total: " + _CartTotal.ToString("C");
        }
     }
}

このメソッドは、各行がバインドされたらショッピング カートの現在までの合計を保持し、GridView の下端の行を更新します。

ここまでで、注文の "レビュー" プレゼンテーションを実装しました。

Page_Load イベントに数行のコードを追加して、空のカートのシナリオを処理しましょう。

protected void Page_Load(object sender, EventArgs e)
{
   CheckOutHeader.InnerText = "Your Shopping Cart is Empty";
   LabelCartHeader.Text = "";
   CheckoutBtn.Visible = false;
}

ユーザーが [Submit] ボタンをクリックすると、送信ボタン クリック イベント ハンドラーで次のコードが実行されます。

protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e)
{
  MyShoppingCart usersShoppingCart = new MyShoppingCart();
  if (usersShoppingCart.SubmitOrder(User.Identity.Name) == true)
    {
    CheckOutHeader.InnerText = "Thank You - Your Order is Complete.";
    Message.Visible = false;
    CheckoutBtn.Visible = false;
    }
  else
    {
    CheckOutHeader.InnerText = "Order Submission Failed - Please try again. ";
    }
}

注文送信プロセスの "主要部分" は、MyShoppingCart クラスの SubmitOrder() メソッドに実装されます。

SubmitOrder は次のことを行います。

  • ショッピング カート内のすべての品目を取得し、それらを使用して、新しい注文レコードと関連する OrderDetails レコードを作成します。
  • 出荷日を計算します。
  • ショッピング カートをクリアします。
//--------------------------------------------------------------------------------------+
public bool SubmitOrder(string UserName)
{
  using (CommerceEntities db = new CommerceEntities())
    {
    try
      {
      //------------------------------------------------------------------------+
      //  Add New Order Record                                                  |
      //------------------------------------------------------------------------+
      Order newOrder = new Order();
      newOrder.CustomerName = UserName;
      newOrder.OrderDate = DateTime.Now;
      newOrder.ShipDate = CalculateShipDate();
      db.Orders.AddObject(newOrder);
      db.SaveChanges();
         
      //------------------------------------------------------------------------+
      //  Create a new OderDetail Record for each item in the Shopping Cart     |
      //------------------------------------------------------------------------+
      String cartId = GetShoppingCartId();
      var myCart = (from c in db.ViewCarts where c.CartID == cartId select c);
      foreach (ViewCart item in myCart)
        {
        int i = 0;
        if (i < 1)
          {
          OrderDetail od = new OrderDetail();
          od.OrderID = newOrder.OrderID;
          od.ProductID = item.ProductID;
          od.Quantity = item.Quantity;
          od.UnitCost = item.UnitCost;
          db.OrderDetails.AddObject(od);
          i++;
          }

        var myItem = (from c in db.ShoppingCarts where c.CartID == item.CartID && 
                         c.ProductID == item.ProductID select c).FirstOrDefault();
        if (myItem != null)
          {
          db.DeleteObject(myItem);
          }
        }
      db.SaveChanges();                    
      }
    catch (Exception exp)
      {
      throw new Exception("ERROR: Unable to Submit Order - " + exp.Message.ToString(), 
                                                               exp);
      }
    } 
  return(true);
}

このサンプル アプリケーションでは、現在の日付に単に 2 日を追加して出荷日を計算します。

//--------------------------------------------------------------------------------------+
DateTime CalculateShipDate()
{
   DateTime shipDate = DateTime.Now.AddDays(2);
   return (shipDate);
}

ここでアプリケーションを実行すると、最初から最後までショッピング プロセスをテストできます。