Share via


第 6 部分:ASP.NET 成員資格

作者 :Joe Stagner

注意

本文撰寫之後,ASP.NET 成員資格提供者已被 ASP.NET 身分識別取代。 強烈建議您將應用程式更新為使用 ASP.NET 身分識別 平臺,而不是本文撰寫時精選的成員資格提供者。 ASP.NET 身分識別的一些優點優於 ASP.NET 成員資格系統,包括 :

  • 更好的效能
  • 改善擴充性和可測試性
  • 支援 OAuth、OpenID Connect 和雙因素驗證
  • 宣告型身分識別支援
  • 與 ASP.Net Core 的較佳互通性

Tailspin Spyworks 示範如何非常簡單,為 .NET 平臺建立功能強大的可調整應用程式。 它示範如何使用 ASP.NET 4 中的絕佳新功能來建置線上商店,包括購物、結帳和管理。

本教學課程系列詳細說明建置 Tailspin Spyworks 範例應用程式所採取的所有步驟。 第 6 部分會新增 ASP.NET 成員資格。

使用 ASP.NET 成員資格

顯示選取 S P 點 NET 組態位置的螢幕擷取畫面。

按一下 [安全性]

顯示按一下 [安全性] 位置的螢幕擷取畫面。

請確定我們使用表單驗證。

顯示如何確認您使用表單驗證的螢幕擷取畫面。

使用 [建立使用者] 連結來建立幾個使用者。

顯示按一下 [建立使用者] 位置的螢幕擷取畫面。

完成時,請參閱方案總管視窗並重新整理檢視。

顯示重新整理檢視位置的螢幕擷取畫面。

請注意,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 方法,將購物車中的暫存會話識別碼變更為該使用者。 (在 .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);
}

針對此範例應用程式的目的,我們只要將兩天新增至目前日期,即可計算出出貨日期。

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

執行應用程式現在可讓我們從頭到尾測試購物程式。