[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
MigrateShoppingCart(model.UserName);
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "用户名或密码输入不正确");
}
}
// 登陆失败,重新显示登陆画面
return View(model);
}
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// 尝试用户注册
MembershipCreateStatus createStatus =
MembershipService.CreateUser(model.UserName,
model.Password, model.Email);
if (createStatus == MembershipCreateStatus.Success)
{
MigrateShoppingCart(model.UserName);
FormsService.SignIn(model.UserName, false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("",
AccountValidation.ErrorCodeToString(createStatus));
}
}
// 注册失败,重新显示登陆视图
ViewBag.PasswordLength = MembershipService.MinPasswordLength;
return View(model);
}
这样就可以了。现在一个用户成功登陆或注册后,该用户仍然能够继续使用他在购物车中的信息。
9.3 创建下订单控制器
鼠标右击Controllers文件夹,追加一个新的名为CheckoutController的控制器。保持“为‘创建’、‘更新’、‘删除’和‘详细信息’方案添加操作方法”复选框为非选取状态,如图9-6所示。
图9-6 添加下订单控制器
首先,为该控制器添加Authorize属性,表示用户在下订单之前首先需要注册及登陆,代码如下所示。
namespace MvcBookStore.Controllers
{
[Authorize]
public class CheckoutController : Controller
请注意:这里添加Authorize属性的方法与为StoreManager控制器添加Authorize属性的方法非常类似,但是在 StoreManager控制器中要求登陆用户的身份必须为管理员,而在CheckoutController控制器中只要求用户登陆,但并不要求用户必 须为管理员。
为了简单起见,本教程中不处理用户的收货信息。
与StoreController控制器中相同,我们需要添加引用BookStoreEntities类的一个实例,对象名为storeDB。为了能够使 用BookStoreEntities类,我们还需添加引用MvcBookStore.Models命名空间。代码如下所示。
using System;
using System.Linq;
using System.Web.Mvc;
using MvcBookStore.Models;
namespace MvcBookStore.Controllers
{
[Authorize]
public class CheckoutController : Controller
{
BookStoreEntities storeDB = new BookStoreEntities();
在CheckoutController控制器中添加如下几个方法:
AddressAndPayment(在GET请求时调用):显示一个表单,允许用户输入收货信息。
AddressAndPayment(在POST请求时调用):验证用户输入的收货信息,处理订单。
Complete:用户下订单成功后显示一个操作完成确认视图。该视图中包括用户的订单号,用以通知用户订单已成功创建。
首先,让我们将Index方法(创建控制器时被自动创建)重命名为AddressAndPayment方法(填写收货信息)。该方法只被用来显示收货信息填写视图,所以不需要任何模型信息,代码如下所示。
//
// GET: /Checkout/AddressAndPayment
public ActionResult AddressAndPayment()
{
return View();
}
在POST请求时调用的AddressAndPayment方法中的处理与StoreManager控制器中的处理非常类似:尝试接收表单信息,并且创建订单。如果失败,则重新显示表单(收货信息填写表单。
在对表单信息验证通过之后,我们将信息保存在订单中,通知ShoppingCart对象来完成订单处理,并且重定向到Complete方法,代码如下所示。
//
// POST: /Checkout/AddressAndPayment
[HttpPost]
public ActionResult AddressAndPayment(FormCollection values)
{
var order = new Order();
TryUpdateModel(order);
try
{
order.Username = User.Identity.Name;
order.OrderDate = DateTime.Now;
//保存订单
storeDB.Orders.Add(order);
storeDB.SaveChanges();
//处理订单信息
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(order);
return RedirectToAction("Complete",new { id = order.OrderId });
}
catch
{
//无效,重新返回显示错误信息
return View(order);
}
}
订单处理成功之后,用户将被重定向到Complete方法。该方法为订单完成通知信息而显示订单号实现一个简单检查,检查该订单是否属于当前登陆用户。代码如下所示。
//
// GET: /Checkout/Complete
public ActionResult Complete(int id)
{
// 验证当前用户是否拥有这张订单
bool isValid = storeDB.Orders.Any(o => o.OrderId == id
&&o.Username == User.Identity.Name);
if (isValid)
{
return View(id);
}
else
{
return View("Error");
}
}
请注意:错误视图将被自动创建在Views文件夹下的Shared文件夹中。
完整的CheckoutController控制器中的代码如代码清单9-1所示。
代码清单9-1 完整的CheckoutController控制器中的代码
using System;
using System.Linq;
using System.Web.Mvc;
using MvcBookStore.Models;
namespace MvcBookStore.Controllers
{
[Authorize]
public class CheckoutController : Controller
{
BookStoreEntities storeDB = new BookStoreEntities();
//
// GET: /Checkout/AddressAndPayment
public ActionResult AddressAndPayment()
{
return View();
}
//
// POST: /Checkout/AddressAndPayment
[HttpPost]
public ActionResult AddressAndPayment(FormCollection
values)
{
var order = new Order();
TryUpdateModel(order);
try
{
order.Username = User.Identity.Name;
order.OrderDate = DateTime.Now;
//保存订单
storeDB.Orders.Add(order);
storeDB.SaveChanges();
//处理订单
var cart =
ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(order);
return RedirectToAction("Complete",new { id =
order.OrderId });
}
catch
{
//无效,重新返回显示错误信息
return View(order);
}
}
//
// GET: /Checkout/Complete
public ActionResult Complete(int id)
{
// 验证当前用户是否拥有这张订单
bool isValid = storeDB.Orders.Any(o => o.OrderId ==
id &&o.Username == User.Identity.Name);
if (isValid)
{
return View(id);
}
else
{
return View("Error");
}
}
}
}
9.4 添加收货信息填写视图
现在,让我们来添加收货信息填写视图。在任意一个AddressAndPayment方法中点击鼠标右键,使用Order(订单)类创建一个强类型视图,使用Edit(编辑)模板,如图9-7所示。
图9-7 添加收货信息填写视图
这个视图将要使用两个我们之前在StoreManager控制器的书籍编辑视图中使用过的两个技巧。
- 我们将使用Html.EditorForModel()帮助器方法来为Order(订单)模型类显示各属性编辑控件。
- 我们将对Order类使用验证属性来强制使用验证规则。
修改表单中的代码,使用Html.EditorForModel()帮助器方法。完整的添加收货信息填写视图中的代码如代码清单9-2所示。
代码清单9-2 完整的添加收货信息填写视图中的代码
@model MvcBookStore.Models.Order
@{
ViewBag.Title = "填写收货信息";
}
<script
src="@Url.Content("~/Scripts/jquery.validate.min.js")"
type="text/javascript"></script>
<script
src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.
min.js")"
type="text/javascript"></script>
@using (Html.BeginForm()) {
<h2>填写收货信息</h2>
<fieldset>
<legend>收货信息</legend>
@Html.EditorForModel()
</fieldset>
<input type="submit" value="提交订单" />
}