zoukankan      html  css  js  c++  java
  • 《Pro ASP.NET MVC 3 Framework》学习笔记之十五

    绑定Shopping Cart

    定义购物车Cart的实体,购物车是我们程序业务领域的一个部分,所以在我们领域模型(Domain Model)里面添加一个cart的实体是合理的。在SportsStore.Domain的Entities文件夹下添加一个Cart的实体类,如下所示:

    View Code

    添加几个测试方法测试下,如下所示:

    View Code

    编辑Views/Shared/ProductSummary.cshtml,如下所示:

    View Code

    当我们提交表单时,会调用CartController下的AddToCart action方法。

    Note:我们通过Html.BeginForm来创建一个表单的,默认情况下form表单是post提交。当然我们可以改变它,使用Get方法提交也可以。但是我们必须谨慎对待,因为HTTP规范要求Get请求必须是幂等的(idempotent),这意味着不能引起任何改变。我们这里向购物车添加Product显然是一个变化的过程,所以用Post最合适。补充下:Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是:GET,POST,PUT,DELETE.即查,改,增,删4个操作。针对这个主题(POST提交还是GET提交)下一章会有更多的讲解,还包括了对如果我们忽略了幂等GET请求产生的后果的解释。

    接着添加一个样式,如下所示:

    View Code

    前面我们用Html.BeginForm方法在每一个Product列表创建了Form。这也意味着,每天点击Add to cart按钮时,会提交对应的Form表单。这可能让我们做WebForm的人有点意外,因为WebForm里面限制了每个页面只能有一个Form。但是asp.net mvc里面没有这个限制,完全可以根据我们的需要来创建Form表单。

    接着创建CartController用来处理Add to cart按钮点击。代码如下所示:

    View Code

    在上面的代码里面,AddToCart和RemoveFromCart方法都调用了RedirectToAction方法。这是用来发送重定向的指令到浏览器,让浏览器请求一个新的URL。这里是让浏览器请求一个调用Index action方法的URL。下面实现这个Index方法并用它来展示Cart的内容。

    我们需要传递两种信息给展示购物车内容的View,分别是Cart对象和展示当用户点击Continue Shopping按钮时的URL。为此,我们创建一个视图模型的类,在Models文件夹创建CartIndexViewModel的类,代码如下:

    View Code

    接着实现Cart controller里面的Index action方法,代码如下:

    View Code

    右键添加视图,如下所示:

    Index View的代码如下所示:

    View Code

    继续添加样式:

    View Code

    现在基本告一段落,可以运行程序看看效果了。接下来是使用模型绑定(Model Binding)。

    asp.net mvc框架使用一种称为model binding的机制将来自HTTP请求创建为C#对象,这样就能够将它们作为参数传递给Controller的Action方法。这也是MVC处理Form表单的原理。例如MVC框架寻找Action方法的参数作为目标,使用model binding从Input元素获取值,并会将这些值转化为Action方法里面参数对应的类型以及相同的参数名称。
    Model binders能够将请求里面任何可用的信息创建为C#类型,这是MVC框架一个非常核心的功能之一。下面我们将创建一个自定义的模型绑定来完善CartController类。这里使用Session对象来存储和管理购物车对象(当然,这可能不符合实际情况,我们只管将注意力放在MVC上吧,呵呵)。

    我们将创建一个自定义的绑定来获取包含在Session里面的Cart对象,MVC框架会创建Cart对象并作为参数传递给CartController的Action方法。MVC的model binding功能是非常强大且可伸缩的。对于这个部分,书的第二部分会有详细的讲解。

    通过实现IModelBinder接口来创建自定义的model binding。在 SportsStore.WebUI里面创建一个新的文件夹Binders,接着在里面创建CartModelBinder.cs.代码如下:

    View Code

    IModeBinder接口里面定义一个方法:BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext).提供的两个参数使我们创建领域模型对象成为可能。ControllerContext providers能够访问Controller类的所有信息,包括了来自浏览器的详细请求信息;ModelBindingContext提供我们要创建model object的信息和工具来简化我们的操作。
    这里主要关注下ControllerContext类,它有一个HttpContext属性,它包含了Session对象,这正是我们需要的。

    我们需要告诉MVC框架使用我们的CartModelBinder类创建Cart的实例,需要修改Global.asax,如下所示:

            protected void Application_Start()
    {
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
    ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
    }

    当MVC收到请求时,比如,AddToCart方法被调用时,它开始寻找action 方法的参数,它将会在可用的绑定列表里面寻找,试图找到一个能够创建每一个参数类型的实例。我们自定义的绑定会被用来创建Cart对象,并且MVC是通过Session功能来实现的。在我们自定义的绑定和默认绑定之间,mvc能够创建必备参数的集合来调用action方法。正是如此才允许我们重构Controller以至于我们不知道在请求被接收时Cart对象是怎样被创立的。

    像这样使用自定义的绑定有几个好处:
    1.我们将创建购物车的逻辑从Controller里面分离出来,这样就允许我们可以改变存储Cart对象的方式而不必去更改Controller。
    2.任何Controller想使用Cart对象,只需要在其Action方法里面声明一个Cart参数即可
    3.较好的进行单元测试

    下面接着完善购物车功能
    这里给购物车增加两个功能:1.允许用户删除购物项 2.在页面顶端增加一个显示购物车详情的功能
    首先修改Views/Cart/Index.cshtml,如下所示:

    View Code

    添加查看购物车详情功能:
    在CartController里面添加一个Summary action方法,如下所示:

    View Code

    Summary方法非常简单,仅仅需要呈现一个View,提供当前购物车作为View Data。当然这里要使用自定义绑定,我需要创建一个partial view。如下所示:

    Summary Partial View的代码如下所示:

    View Code

    因为我们在每个页面都要显示,所有需要在_Layout.cshtml里面进行定义,如下所示:

    <!DOCTYPE html>
    <html>
    <head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    </head>
    <body>
    <div id="header">
    @{Html.RenderAction("Summary", "Cart");}
    <div class="title">
    Sports Store</div>
    </div>
    <div id="categories">
    @{Html.RenderAction("Menu", "Nav");}
    </div>
    <div id="content">
    @RenderBody()
    </div>
    </body>
    </html>

    接着添加样式,如下所示:

    Vi


     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2319996.html
Copyright © 2011-2022 走看看