第 6 部:ASP.NET メンバーシップ

作成者: Joe Stagner

注意

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

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

Tailspin Spyworks は、.NET プラットフォーム用の強力でスケーラブルなアプリケーションを作成することが非常にシンプルであることを示しています。 ASP.NET 4 の優れた新機能を使用して、ショッピング、チェックアウト、管理などのオンライン ストアを構築する方法を示します。

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

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

[A S P dot NET Configuration]\(S P ドット NET 構成\) を選択する場所を示すスクリーンショット。

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

[セキュリティ] をクリックする場所を示すスクリーンショット。

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

フォーム認証を使用していることを確認する方法を示すスクリーンショット。

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

[Create User]\(ユーザーの作成\) をクリックする場所を示すスクリーンショット。

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

ビューを更新する場所を示すスクリーンショット。

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

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

まず、CheckOut.aspx ページを作成します。

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

これを行うには、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 をユーザーの一時セッション 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;
}

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

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);
}

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