6부: ASP.NET 멤버 자격

작성자 : Joe Stagner

참고

이 문서가 작성된 이후 ASP.NET 멤버 자격 공급자는 ASP.NET ID로 대체되었습니다. 이 문서를 작성할 때 추천하는 멤버 자격 공급자가 아닌 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 멤버 자격 작업

SP 점 NET 구성을 선택할 위치를 보여 주는 스크린샷

보안을 클릭합니다.

보안을 클릭할 위치를 보여 주는 스크린샷

양식 인증을 사용하고 있는지 확인합니다.

양식 인증을 사용하고 있는지 확인하는 방법을 보여 주는 스크린샷

"사용자 만들기" 링크를 사용하여 몇 명의 사용자를 만듭니다.

사용자 만들기를 클릭할 위치를 보여 주는 스크린샷

완료되면 솔루션 탐색기 창을 참조하고 보기를 새로 고칩니다.

보기를 새로 고칠 위치를 보여 주는 스크린샷

ASPNETDB를 확인합니다. MDF fine이 생성되었습니다. 이 파일에는 멤버 자격과 같은 핵심 ASP.NET 서비스를 지원하는 테이블이 포함되어 있습니다.

이제 체크 아웃 프로세스 구현을 시작할 수 있습니다.

먼저 CheckOut.aspx 페이지를 만듭니다.

체크 아웃.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;
}

사용자가 "제출" 단추를 클릭하면 제출 단추 클릭 이벤트 처리기에서 다음 코드를 실행합니다.

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

이제 애플리케이션을 실행하면 쇼핑 프로세스를 처음부터 끝까지 테스트할 수 있습니다.