ASP.NET MVC3书店--第九节 注册与下订单(第一部分)

来源:互联网 发布:大数据的特征不包括 编辑:程序博客网 时间:2024/05/17 08:39
 在本节中,我们将要创建一个下订单控制器,该控制器将获取购买者的收货地址与付款信息。在下订单之前,用户首先需要在网站中进行注册,因此在访问这个控制器的时候需要进行用户身份认证处理。

 点击图9-1中所示视图中的“结算”链接之后,用户将进入下订单处理过程。

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)

图9-1 点击“结算”链接 

    如果用户尚未登陆,他们将会看见登陆视图,如图9-2所示。

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)



图9-2 登陆视图  

    用户成功登陆之后,将看见收货信息填写视图,如图9-3所示。

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)

图9-3 收货信息填写视图

    填写完毕收货信息并提交之后,他们将会看见订单完成通知视图,如图9-4所示。  

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)

图9-4 订单完成通知视图

    企图查看一个不存在的订单或者非注册用户的订单信息时,他们会看见如图9-5中所示的错误视图。  

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)

图9-5 错误视图

9.2 转入购物车中的信息

    当匿名用户点击“结算”链接的时候,他们将会提示需要注册并登陆。用户当然希望登陆后能够继续使用在登陆之前他们放入购物车中的信息,所以我们需要在用户注册并且登陆之后取得他们在注册或登陆之前放入购物车中的信息。

    这个处理是非常简单的,因为我们的ShoppingCart类中已经有了一个方法来将该用户登陆后的用户名与登陆前的购物车中的信息合并起来,我们只需要在用户注册及登陆后直接调用这个方法就可以了。

    打开之前我们在处理用户身份认证时追加的AccountController类,假如如下所示的MigrateShoppingCart方法。   

private void MigrateShoppingCart(string UserName){    // 获取登陆用户购物车中的信息    var cart = ShoppingCart.GetCart(this.HttpContext);     cart.MigrateCart(UserName);    Session[ShoppingCart.CartSessionKey] = UserName;}

    接下来,修改在HttpPost请求时调用的LogOn方法,当用户登陆成功后调用MigrateShoppingCart,代码如下所示。 
[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);}

    在Register这个HttpPost请求时调用的action方法中做出同样的修改,当用户注册成功时立即读取用户购物车中的信息。 
[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所示。

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)

图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/AddressAndPaymentpublic 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/Completepublic 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(FormCollectionvalues)        {            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所示。

ASP.NET <wbr>MVC3书店--第九节 <wbr>注册与下订单(第一部分)

图9-7 添加收货信息填写视图

    这个视图将要使用两个我们之前在StoreManager控制器的书籍编辑视图中使用过的两个技巧。

  • 我们将使用Html.EditorForModel()帮助器方法来为Order(订单)模型类显示各属性编辑控件。
  • 我们将对Order类使用验证属性来强制使用验证规则。

    修改表单中的代码,使用Html.EditorForModel()帮助器方法。完整的添加收货信息填写视图中的代码如代码清单9-2所示。

    代码清单9-2 完整的添加收货信息填写视图中的代码

@model MvcBookStore.Models.Order@{    ViewBag.Title = "填写收货信息";}<scriptsrc="@Url.Content("~/Scripts/jquery.validate.min.js")"type="text/javascript"></script><scriptsrc="@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="提交订单" />}