Часть 6. Членство в ASP.NET
Примечание
С момента написания этой статьи поставщики членства ASP.NET были заменены ASP.NET Identity. Мы настоятельно рекомендуем обновить приложения для использования платформы ASP.NET Identity , а не поставщиков членства, которые были представлены на момент написания этой статьи. ASP.NET Identity имеет ряд преимуществ по сравнению с системой членства ASP.NET, включая :
- более высокая производительность;
- Улучшенная расширяемость и тестируемость
- Поддержка OAuth, OpenID Connect и двухфакторной проверки подлинности
- Поддержка удостоверений на основе утверждений
- Улучшенное взаимодействие с ASP.Net Core
Tailspin Spyworks демонстрирует, насколько просто создавать мощные масштабируемые приложения для платформы .NET. В нем показано, как использовать новые функции ASP.NET 4 для создания интернет-магазина, включая покупки, оформления заказа и администрирования.
В этой серии руководств подробно описаны все шаги, предпринятые для создания примера приложения Tailspin Spyworks. Часть 6 добавляет ASP.NET членство.
Работа с ASP.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, чтобы задать имя сеанса только что вошедшего пользователя и изменить идентификатор временного сеанса в корзине на идентификатор пользователя, вызвав метод MigrateCart в классе MyShoppingCart. (Реализовано в 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'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 задает обработчик событий ondatabound с именем MyList_RowDataBound поэтому давайте реализуем этот обработчик событий следующим образом.
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'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. ";
}
}
"Мясо" процесса отправки заказа должно быть реализовано в методе SubmitOrder() класса MyShoppingCart.
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);
}
Запуск приложения позволит нам протестировать процесс покупки от начала до конца.