Nancy简单实战之NancyMusicStore(四):实现购物车

原文:Nancy简单实战之NancyMusicStore(四):实现购物车

前言

上一篇,我们完成了商品的详情和商品的管理,这一篇我们来完成最后的一个购物车功能。

购物车,不外乎这几个功能:添加商品到购物车,删除购物车中的商品,对购物车中的商品进行结算。

MVC MusicStore中,在Models文件夹中添加了一个ShoppingCart类来处理这一块的内容

这个类就类似我们的业务逻辑层,所以这里也采用了和它一样的做法。

取购物车

首先来看一下取购物车这个静态方法:

public static ShoppingCart GetCart(NancyContext context)
{var cart = new ShoppingCart();cart.ShoppingCartId = cart.GetCartId(context);return cart;
}

取购物车,其实只是给购物车类里面的ShoppingCartId赋值,而ShoppingCartId值是来自GetCartId方法:

public string GetCartId(NancyContext context)
{if (context.Request.Session[CartSessionKey] == null){if (context.CurrentUser != null){context.Request.Session[CartSessionKey] = context.CurrentUser.UserName;}else{Guid tempCartId = Guid.NewGuid();context.Request.Session[CartSessionKey] = tempCartId.ToString();}}return context.Request.Session[CartSessionKey].ToString();
}

在MVC MusicStrore中,这个方法的参数用的是HttpContextBase,而在Nancy中,Nancy有自己的Context

所以自然就是直接用Nancy自带的Context。这里是每次都会为新用户创建一个guid存储在session中

并用这个session作为购物车的唯一标识。

在Nancy中,用到了session的话,需要在启动器中启用Session,不然Session会一直是空的。

我们在CustomerBootstrapper类的ApplicationStartup方法中添加启动Cookie的代码,具体如下:

protected override void ApplicationStartup(TinyIoCContainer container,IPipelines pipelines)
{//enable the cookieCookieBasedSessions.Enable(pipelines);//Prevent errors on LinuxStaticConfiguration.DisableErrorTraces = false;
}

购物车商品数量

还记得我们在布局_Layout.cshtml里面还有一个购物车中的商品数量还没有实现。我们现在把这个功能补上。

在ShoppingCart中添加下面取数的方法,这个方法是根据购物车的id去数据取出相应的数据。

public int GetCount()
{string cmd = "public.get_total_count_by_cartid";var res = DBHelper.ExecuteScalar(cmd, new{cid = ShoppingCartId}, null, null, CommandType.StoredProcedure);return Convert.ToInt32(res);
}

然后我们新建一个ShopCartModule.cs,并在构造函数中添加取数的方法。

Get["/cartsummary"] = _ =>
{var cart = ShoppingCart.GetCart(this.Context);return Response.AsJson(cart.GetCount());
};

最后在_Layout.cshtml中用ajax调用这个方法即可:

 $.ajax({url: "/shoppingcart/cartsummary",method: "get",dataType: "json",success: function (res) {$("#cart-status").text('Cart (' + res + ')');}
});

这样我们就彻底把布局页完成了。下面是具体的效果

12932

下面就专注购物车的其他实现了。

添加商品到购物车

添加商品到购物车,有这两种情况:

  • 添加了一个购物车中没有的商品(要向购物车中插一条记录)

  • 添加了一个购物车中已经有了的商品(要向购物车中更新一条记录)

所以我们就可以得到下面的实现(ShoppingCart):

public void AddToCart(Album album)
{string getItemCmd = "public.get_cart_item_by_cartid_and_albumid";var cartItem = DBHelper.QueryFirstOrDefault<Cart>(getItemCmd, new{cid = ShoppingCartId,aid = album.AlbumId}, null, null, CommandType.StoredProcedure);string addToCartCmd = string.Empty;if (cartItem == null){// Create a new cart item if no cart item existsAddCartItem(cartItem, album.AlbumId);}else{UpdateCartItem(cartItem);}
}

在添加之前都要向根据购物车标识和专辑(商品)标识去判断。此时我们在Module中的实现就比较简单了

Get["/addtocart/{id:int}"] = _ =>
{int id = 0;if (int.TryParse(_.id, out id)){string cmd = "public.get_album_by_aid";var addedAlbum = DBHelper.QueryFirstOrDefault<Album>(cmd, new{aid = id}, null, null, CommandType.StoredProcedure);var cart = ShoppingCart.GetCart(this.Context);cart.AddToCart(addedAlbum);}return Response.AsRedirect("~/");
};

后台逻辑处理好了,我们把商品加入购物车的入口在那呢?入口就在商品详情页下面的【Add to cart】按钮

12955

当我们把加入购物车后,可以看到右上角的数量在改变,同时跳转回了首页。

12959

购物车首页

我们已经完成了添加商品到购物车,但是我们还看不到我们购物车里面有些什么商品,所以要有一个购物车首页。

购物车的首页,本质就是一个列表,这个列表所列了购物车内的所有商品,包含了这些商品的基本信息和购物车的订单总金额。

Get["/index"] = _ =>
{var cart = ShoppingCart.GetCart(this.Context);// Set up our ViewModelvar viewModel = new ShoppingCartViewModel{CartItems = cart.GetCartItems(),CartTotal = cart.GetTotal()};// Return the viewreturn View["Index", viewModel];
};

视图如下 :

@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<NancyMusicStore.ViewModels.ShoppingCartViewModel>
@{ViewBag.Title = "Shopping Cart";
}
<h3><em>Review</em> your cart:
</h3>
<p class="button"><a href="javascript:;">Checkout >></a>
</p>
<div id="update-message">
</div>
<table><tr><th>Album Name</th><th>Price (each)</th><th>Quantity</th><th></th></tr>@foreach (var item in Model.CartItems){<tr id="row-@item.RecordId"><td><a href="/store/details/@item.AlbumId">@item.Title</a></td><td>@item.Price</td><td id="item-count-@item.RecordId">@item.Count</td><td><a href="javascript:void(0);" class="RemoveLink" data-id="@item.RecordId">Remove from cart</a></td></tr>}<tr><td>Total</td><td></td><td></td><td id="cart-total">@Model.CartTotal</td></tr>
</table>

具体效果如下所示:

shoppingcart

从购物车中删除商品

删除购物车中的商品也是同样的有两种情况

  • 一种是让购物车中的商品数量减1

  • 一种是从购物车中直接删掉商品,不同的是删除的同时返回了商品的数量,这个数量用于在页面展示。

public int RemoveFromCart(int id)
{string getItemCmd = "public.get_cart_item_by_cartid_and_recordid";var cartItem = DBHelper.QueryFirstOrDefault<Cart>(getItemCmd, new{cid = ShoppingCartId,rid = id}, null, null, CommandType.StoredProcedure);int itemCount = 0;if (cartItem != null){                if (cartItem.Count > 1){UpdateCartItemCount(cartItem, itemCount);                   }else{RemoveCartItem(cartItem.RecordId);}}return itemCount;
}

同时还要在购物车列表页面添加相应的JS处理

@section scripts{<script type="text/javascript">$(function () {$(".RemoveLink").click(function () {var recordToDelete = $(this).attr("data-id");if (recordToDelete != '') {$.post("/shoppingcart/removefromcart", { "id": recordToDelete },function (data) {if (data.ItemCount == 0) {$('#row-' + data.deleteid).fadeOut('slow');} else {$('#item-count-' + data.deleteId).text(data.itemCount);}$('#cart-total').text(data.cartTotal);$('#update-message').text(data.message);$('#cart-status').text('Cart (' + data.cartCount + ')');});}});});</script>
}

最后的话就是结算,下面进入我们的结算操作

购物车结算

购物车结算,也就是提交订单,也就是填写一些用户的相关信息,比如:姓名、地址、联系电话等等这些信息,见下图。

checkout

我们在Modules文件夹中添加一个CheckOutModule.cs用来处理结算相关的功能。

要结算,必须要登录,所以我们要首先添加需要授权的这句代码this.RequiresAuthentication();

然后再考虑其他事情。

提交订单的后台操作如下:

Post["/addressandpayment"] = _ =>
{var order = this.Bind<Order>();order.Username = this.Context.CurrentUser.UserName;order.OrderDate = DateTime.UtcNow;string cmd = "public.add_order";var res = DBHelper.ExecuteScalar(cmd, new{odate = order.OrderDate,uname = order.Username,fname = order.FirstName,lname = order.LastName,adr = order.Address,cn = order.City,sn = order.State,pcode = order.PostalCode,cname = order.Country,ph = order.Phone,ea = order.Email,t = order.Total}, null, null, CommandType.StoredProcedure);if (Convert.ToInt32(res) != 0){order.OrderId = Convert.ToInt32(res);var cart = ShoppingCart.GetCart(this.Context);cart.CreateOrder(order);string redirectUrl = string.Format("/checkout/complete/{0}", res.ToString());return Response.AsRedirect(redirectUrl);}return View["AddressAndPayment"];
};

先是创建了一张订单,这张订单只包含了一些用户信息。订单创建好了之后才去创建订单明细,最后就是返回订单完成页:

complete

创建订单明细的方法也是写在Models下面的ShoppingCart中,具体如下:

public int CreateOrder(Order order)
{decimal orderTotal = 0;var cartItems = GetCartItems();                        foreach (var item in cartItems){                AddOrderDetails(new OrderDetail{AlbumId = item.AlbumId,OrderId = order.OrderId,UnitPrice = item.Price,Quantity = item.Count});// Set the order total of the shopping cartorderTotal += (item.Count * item.Price);}UpdateOrderTotal(order.OrderId, orderTotal);         // Empty the shopping cartEmptyCart();// Return the OrderId as the confirmation numberreturn order.OrderId;
}

这里做的操作主要有三个:

  1. 把购物车中的商品插入到订单明细表中
  2. 更新订单主表的总金额
  3. 清空当前的购物车

到这里,我们的NancyMusicStore已经是到了收尾阶段。就差部署上线了啊!!

所以在下一篇,将是介绍Nancy的部署,分别在Windows和Linux下部署。

本文也已经同步到 Nancy之大杂烩

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390407.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剑指 Offer 32 - I. 从上到下打印二叉树

从上到下打印出二叉树的每个节点&#xff0c;同一层的节点按照从左到右的顺序打印。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3/ \9 20/ \15 7返回&#xff1a; [3,9,20,15,7] 提示&#xff1a; 节点总数 < 1000 解题思路 使用队列实现层序遍历 代码 /*** …

数据库表命名 单数复数_数据是还是数据是? “数据”一词是单数还是复数?

数据库表命名 单数复数Ill cut right to the chase: the word "data" is plural. Its the plural form of Latin word "datum." Many data. One datum.我将紧追其后&#xff1a;“数据”一词是复数形式。 它是拉丁文“基准”的复数形式。 许多数据。 一个基…

《七步掌握业务分析》读书笔记六

分析技术和呈现格式 词汇表 强有力沟通的一个重要内容是一致地使用术语和惯用语。每次谈话都涉及对术语的共同理解。 工作流图&#xff08;也称为流程图、UNL活动图和过程图&#xff09; 工作流程把一个或多个业务过程的细节可视化地呈现出来&#xff0c;以澄清理解或提出过程改…

Mysql数据库--语句整理/提升/进阶/高级使用技巧

一、基础 1、说明&#xff1a;创建数据库CREATE DATABASE database-name 2、说明&#xff1a;删除数据库drop database dbname3、说明&#xff1a;备份sql server--- 创建 备份数据的 deviceUSE masterEXEC sp_addumpdevice disk, testBack, c:\mssql7backup\MyNwind_1.dat--- …

1104. 二叉树寻路

在一棵无限的二叉树上&#xff0c;每个节点都有两个子节点&#xff0c;树中的节点 逐行 依次按 “之” 字形进行标记。 如下图所示&#xff0c;在奇数行&#xff08;即&#xff0c;第一行、第三行、第五行……&#xff09;中&#xff0c;按从左到右的顺序进行标记&#xff1b;…

javascript 代码_如何开始对JavaScript代码进行单元测试

javascript 代码We all know we should write unit tests. But, its hard to know where to start and how much time to devote to tests compared to actual implementation. So, where to start? And is it just about testing code or do unit tests have other benefits?…

个人作业——软件工程实践总结作业

一、请回望暑假时的第一次作业&#xff0c;你对于软件工程课程的想象 1&#xff09;对比开篇博客你对课程目标和期待&#xff0c;“希望通过实践锻炼&#xff0c;增强计算机专业的能力和就业竞争力”&#xff0c;对比目前的所学所练所得&#xff0c;在哪些方面达到了你的期待和…

(转)在阿里,我们如何管理代码分支?

阿里妹导读&#xff1a;代码分支模式的选择并没有绝对的正确和错误之分&#xff0c;关键是与项目的规模和发布节奏相匹配。阿里协同研发平台在经过众多实践历练后&#xff0c;总结出了一套独创的分支管理方法&#xff1a;AoneFlow&#xff0c;通过兼备灵活高效与简单实用的流程…

WIN10系统 截图或者某些程序时屏幕会自动放大怎么办

右击这个应用程序&#xff0c;兼容性&#xff0c;以兼容模式运行&#xff0c;同时勾选高DPI设置时禁止显示缩放即可

css背景图片添加url_CSS背景图片–如何向您的Div添加图片URL

css背景图片添加urlSay you want to put an image or two on a webpage. One way is to use the background-image CSS property. 假设您要在网页上放置一两个图片。 一种方法是使用background-image CSS属性。 This property applies one or more background images to an el…

golang基础01

1.环境变量&#xff1a;go env//代码目录和第三方库文件set GOPATHC:\Users\hanxiaodong\go//go安装目录set GOROOTC:\Gopath里要配置&#xff1a;goroot/bin;和gopath/bin; gopath目录下三个文件夹&#xff1a;pkg&#xff1a;编译好的库文件 .a 文件bin&#xff1a;可执行文件…

hugo 能做web开发吗_如何自托管Hugo Web应用

hugo 能做web开发吗After hosting with Netlify for a few years, I decided to head back to self hosting. There are a few reasons for that, but the main reasoning was that I had more control over how things worked. 在Netlify托管了几年之后&#xff0c;我决定回到…

资源 | 深度学习课程入门与介绍

【1】Andrew NG Deep Learning.ai http://deeplearning.ai/网易云课堂&#xff08;中文字幕&#xff09;&#xff1a;http://mooc.study.163.com/smartSpec/detail/1001319001.htm推荐理由&#xff1a;Andrew Ng老师是讲课的能手&#xff0c;很多人认识他是从Stanford的经典《机…

PostCSS 以及 cssnext语法

本文是对近两天学习postcss的总结&#xff0c;在这里分享给大家。 如有错误&#xff0c;还请指正&#xff01; 什么是postcss postcss 一种对css编译的工具&#xff0c;类似babel对js的处理&#xff0c;常见的功能如&#xff1a; 1 . 使用下一代css语法 2 . 自动补全浏览器前缀…

5187. 收集足够苹果的最小花园周长

给你一个用无限二维网格表示的花园&#xff0c;每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| |j| 个苹果。 你将会买下正中心坐标是 (0, 0) 的一块 正方形土地 &#xff0c;且每条边都与两条坐标轴之一平行。 给你一个整数 neededApples &#xff0c…

虚拟机 VMware Workstation12 安装OS X 系统

Windows下虚拟机安装Mac OS X —– VMware Workstation12安装Mac OS X 10.11本文即将介绍WIN虚拟MAC的教程。完整详细教程&#xff08;包含安装中的一些问题&#xff09;【并且适用其他mac os x版本】Windows下 VM12虚拟机安装OS X 10.11(详细教程) 工具/原料 Mac OS X 10.11 镜…

aws dynamodb_DynamoDB备忘单–您需要了解的有关2020 AWS认证开发人员助理认证的Amazon Dynamo DB的所有信息

aws dynamodbThe emergence of cloud services has changed the way we build web-applications. This in turn has changed the responsibilities of a Web Developer. 云服务的出现改变了我们构建Web应用程序的方式。 反过来&#xff0c;这改变了Web开发人员的职责。 We use…

北大CIO走进龙泉寺交流研讨会圆满举行

缘起 2016年4月16日&#xff0c;北京大学信息化与信息管理研究中心秘书长姚乐博士与国家非物质文化遗产蔚县剪纸传承人周淑英女士一起在龙泉寺拜见了中国佛教协会会长、龙泉寺主持学诚法师。在拜见学诚法师时&#xff0c;姚乐博士与学诚法师聊到了“贤二机器僧”和人工智能。姚…

负载均衡种类

http://blog.csdn.net/zhoudaxia/article/details/23672319DNS DNS轮询是最简单的负载均衡方式。以域名作为访问入口&#xff0c;通过配置多条DNS A记录使得请求可以分配到不同的服务器。DNS轮询没有快速的健康检查机制&#xff0c;而且只支持WRR的调度策略导致负载很难“均衡”…

代码流星雨是什么形式_为什么要在2020年与流星合作

代码流星雨是什么形式Meteor, an allegedly dead development platform, is still alive and can bring massive value to your everyday coding experience.Meteor&#xff0c;据称已失效的开发平台&#xff0c;仍然有效&#xff0c;可以为您的日常编码体验带来巨大的价值。 …