构建一个真实的应用电子商务SportsStore(十一)

我们的项目已经进入了非常好的良性循环,项目中涵盖了多数现在的主流开源框架的使用。就Ninject而言,我们的运用是非常的成功,没有任何一点多余的代码,你不在每个控制器的构造函数中去调用Ninject的任何代码,控制器工厂类会自动为你注入你想要的对象,这一点希望大家能记住并运用到你今后的项目中,之所以作为重点提及它,是因为网上有很多错误的教程和做法,既没有显示出Ninject的本质,也误导了读者。今天,我们就对该项目的剩余功能做个完结,下篇我们将把注意力集中在网络安全上,没有跟上进度的兄弟,或没有理解的很透的兄弟,一定要多读几遍,多调试下代码,有很多细节的东西,我们没有写太多的笔墨,这并不是我懒,而是我觉得那些对你没有问题,你搞得定它!

添加模块验证

我们的管理员也是人,所以也有犯错误的可能,而且几乎是一定会犯错误。所以,我们也要添加些验证的规则,去规避错误,例如在价格中输入了负数,商品简介没有填写等,而我们还是使用系统的功能和特性去完成这些工作,这也有助于我们对系统的理解,现在我们就在Product类上添加以下特性:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc; namespace SportsStore.Domain.Entities
{
public class Product
{
[HiddenInput(DisplayValue = false)]
public int ProductID { get; set; }
[Required(ErrorMessage = "请输入商品名称")]
public string Name { get; set; } [DataType(DataType.MultilineText)]
[Required(ErrorMessage = "请输入商品介绍")]
public string Description { get; set; }
[Required]
[Range(0.01, double.MaxValue, ErrorMessage = "请输入一个有效的价格")]
public decimal Price { get; set; }
[Required(ErrorMessage = "请指定一个商品类别")]
public string Category { get; set; }
}
}

编辑一个Product时,Html.EditorForModel helper 方法就创建一个form元素,MVC框架添加markup并加载了CSS类,这些都是显示验证错误所必需的,运行一下程序,我们的验证规则开始发挥作用了:

结果并非我们所预期的,而是抛出了一个异常,仔细分析原因,原来是因为我们改动了数据模型,导致EFDbContext不再适用于原来的数据库,我们需要做数据迁移。

Entity Framework Migrations

处理这种情况,我们可能有下面几种选择方案:

  • 删除数据库并重建它, 当这将丢失数据库中的数据, 而且你的老板和客户都会不喜欢这种方案。
  • 根据错误提示做Code-Migration。

那么,我们怎么该怎么做呢?

Step 1:在Global.asax, 在Application_Start 事件中添加下行代码:

Database.SetInitializer<EFDbContext>(null); //For Changes

哦对了,如果你的程序不能认出Database这个名字,你要添加一条引用语句在代码的引用部分

using System.Data.Entity;

Step 2:打开程序包管理控制台,工具/库程序包管理器/程序包管理控制台,执行下列命令:

PM> Enable-Migrations -ProjectName SportsStore.Domain -ContextTypeName SportsStore.Domain.Concrete.EFDbContext

执行命令后, 你应该在工程文件夹下,看到一个新文件夹被命名为 ‘Migrations’ 的文件夹。

  • Configuration - ‘Seed’ 方法.
  • InitialCreate - Up 和Down 方法.

Step 3 执行下面的命令:
PM> add-migration -ProjectName SportsStore.Domain  Initial

这个命令将会在‘Migrations’ 文件夹中添加一个命名为<TimeStamp>_Initial.cs的文件。

Step 4:PM> update-database -ProjectName SportsStore.Domain

更新数据库,现在运行程序,你应该可以看到预期的结果了

现在我们可以把刚才添加到Global.asax的Application_Start 事件中的代码再完善一下:

Database.SetInitializer<EFDbContext>(new CreateDatabaseIfNotExists<EFDbContext>()); //For Changes

我们的验证方法并不科学,不但导致程序不可读,而且,每次验证都要在服务器端处理,而不能直接在浏览器端解决,这很浪费资源和时间,之所以绕出这么远,主要是为了掩饰EF框架数据迁移的用法,如果你觉得这是有助于学习,你得到了帮助,那么请为我留下个推荐吧!

改用客户端校验

打开_AdminLayout.cshtml文件,添加如下语句:

    <script src="~/Scripts/jquery-1.7.1.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<title></title>

你可以在通过设置web.config文件,去关闭整个工程的客户端验证:

<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />

<add key="Email.WriteAsFile" value="true"/>
</appSettings>

添加新产品

创建一个新的action方法到AdminController类:

public ViewResult Create()
{
return View("Edit", new Product());
}

我们这个创建的方法没有自己对应的View,我们重用了Edit view,一个action方法链接到一个存在的view上,是个完美的设计,在这里,我们注入一个新的产品对象作为View model,使Edit view弹出一个空窗体,然而,我们还是过于乐观了,现在的代码还不是我们所期望的结果。因为它不能返回到初始的Edit action,我们需要修改一下Views/Admin/Edit.cshtml文件:

@model SportsStore.Domain.Entities.Product
@{
ViewBag.Title = "Admin: 编辑" + @Model.Name;
Layout = "~/Views/Shared/_AdminLayout.cshtml";
} <h1>Edit @Model.Name</h1> @using (Html.BeginForm("Edit", "Admin"))
{
@Html.EditorForModel()
<input type="submit" value="保存" />
@Html.ActionLink("取消并返回", "Index")
}

我们为BeginForm()添加了两个参数,保证返回的地址是正确的。

删除商品

添加一个新的方法到IProductRepository接口:

Product DeleteProduct(int productID);

然后到EFProductRepository类中去实现这个方法:

public Product DeleteProduct(int productID)
{
Product dbEntry = context.Products.Find(productID);
if (dbEntry != null)
{
context.Products.Remove(dbEntry);
context.SaveChanges();
}
return dbEntry;
}

最后一步,我们要在AdminController中添加一个删除的action方法,这里我们只要支持Post,因为这个删除的操作不是幂等操作,幂等操作不在本系了教程之内,如果有朋友感兴趣,可以去查阅相关资料,这里你只需知道,Get方法make一个请求时,不需要用户的显示同意,就会释放浏览器和缓存,这个极为危险的,为了回避这一点,我们必须使用Post。

        [HttpPost]
public ActionResult Delete(int productId)
{ Product deletedProduct = repository.DeleteProduct(productId);
if (deletedProduct != null)
{
TempData["message"] = string.Format("{0} was deleted",
deletedProduct.Name);
}
return RedirectToAction("Index");
}

到AdminTest文件中,添加测试方法吧:

        [TestMethod]
public void Can_Delete_Valid_Products() {
// Arrange - create a Product
Product prod = new Product { ProductID = 2, Name = "Test" };
// Arrange - create the mock repository
Mock<IProductsRepository> mock = new Mock<IProductsRepository>();
mock.Setup(m => m.Products).Returns(new Product[] {
new Product {ProductID = 1, Name = "P1"},
prod,
new Product {ProductID = 3, Name = "P3"},
}.AsQueryable());
// Arrange - create the controller
AdminController target = new AdminController(mock.Object);
// Act - delete the product
target.Delete(prod.ProductID);
// Assert - ensure that the repository delete method was
// called with the correct Product
mock.Verify(m => m.DeleteProduct(prod.ProductID));
}

运行它去看看今天的成果吧!如果你完全理解和掌握了这个系列的所有知识点,现在你已经是MVC的专家了,你可以应用这些技术到你的项目中。今天就到这里吧,下篇我们将进行最后的润色,争取做到完美收官!有任何问题可直接留言或Email给我,请继续保持你热情,让我们善始善终吧!

打开VS2012的创建单元测试功能

在VS2010中,在类中点击右键,有一个创建创建单元测试命令,可以很方便的生成单元测试项目和代码。但不知道为什么VS2012反而没有这个功能。

网上搜了一下,好在这个功能是可以通过配置打来的。

传送门:http://www.cnblogs.com/WilsonWu/archive/2013/05/22/3092584.html

但作者用的是英文的VS,我们来个汉化版本的。并说明一下需要注意的地方。

1 打开  工具--自定义

2 选择 上下文菜单--编辑器上下文菜单|代码窗口

3 在这里我们可以看到“创建单元测试”这个菜单了,将它移到运行测试菜单下面

关闭VS并重启

重启后再对着类名,点击右键,发现上下文菜单中已经出现了“创建单元测试”按钮,但它是灰色的,并不能使用。但我们离成功不远了。

重启很重要,如果不重启,菜单出不来。

5 解决方案中右键,添加--新建项目,添加一个单元测试项目。

如图:

6 右键单元测试项目,添加--单元测试

哈哈,此时大功告成,你再返回非测试项目项目中,对着类名点击右键,就可以看到“创建单元测试”可以用了。

PS:好像重新打开项目的时候,“创建单元测试”都会是灰色的,但重新执行一下步骤6就OK了。

如果我的文章对你有帮助,就点一下推荐吧.(*^__^*)
 
 
标签: .NET

构建一个真实的应用电子商务SportsStore(十一)的更多相关文章

  1. 使用MVC4,Ninject,EF,Moq,构建一个真实的应用电子商务SportsStore

    05 2013 档案 使用MVC4,Ninject,EF,Moq,构建一个真实的应用电子商务SportsStore(一) 摘要: 完成SportsStore电子商务平台,你将学会: 1.使用MVC4开 ...

  2. 构建一个真实的应用电子商务SportsStore(十)

    构建一个真实的应用电子商务SportsStore(十) 我们现在还需要为管理员提供一个途径,使他能方便的管理网站的商品目录,这也是所有网站都需要的功能,常用到了几乎所有开发人员都要开发这种功能的地步, ...

  3. 构建一个真实的应用电子商务SportsStore9

    使用MVC4,Ninject,EF,Moq,构建一个真实的应用电子商务SportsStore(九) 实在不好意思,好久没有更新了,我不想找些客观原因来解释,只想请大家见谅!现在我们继续我们的项目,客户 ...

  4. springboot程序构建一个docker镜像(十一)

    准备工作 环境: linux环境或mac,不要用windows jdk 8 maven 3.0 docker 对docker一无所知的看docker教程. 创建一个springboot工程 引入web ...

  5. 构建具有用户身份认证的 React + Flux 应用程序

    原文:Build a React + Flux App with User Authentication 译者:nzbin 译者的话:这是一篇内容详实的 React + Flux 教程,文章主要介绍了 ...

  6. 初窥构建之法——记2020BUAA软工个人博客作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 完成一次完整的软件开发经历并以博客的方式记录开发过程的心得掌握 ...

  7. ApacheCN React 译文集 20211118 更新

    React 入门手册 零.前言 一.React 和 UI 设计简介 二.创建组件 三.管理用户交互 React 全栈项目 零.前言 一.使用 MERN 释放 React 应用 二.准备开发环境 三.使 ...

  8. Angular2 入门

    1. 说明 该文档为Angular2的入门文档,可以根据该文档的内如做出一个“helloworld”类型的Angualr2入门程序,通过该文档可以初步了解Angular2的相关知识以及开发流程,同时搭 ...

  9. Selenium测试规划

    开源工具经过近几年的发展,已经出现了一大批成熟的可应用到实际项目中的产品,其中,在WEB自动化测试领域,Selenium支持广泛的浏览器和脚本开发语言,高效的执行效率,获得广泛的应用. 本课程结合Se ...

随机推荐

  1. Swift入门教程:基本语法(一)

          简介:                                                                                       什么是S ...

  2. hibernate之使用Annotation注解搭建项目

    之前开发都是使用xml配置来开发项目,开发起来特别繁琐 大家会发现通过注解大大简化了我们开发流程,使我们从繁琐的XML配置中解放出来. 第一步:新建一个javaweb项目.并将hibernate需要的 ...

  3. sp.Net MVC4 + Oracle + EasyUI + Bootstrap2

    Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 第二章   Asp.Net MVC4 + Oracle + EasyUI + Bootstrap 第二章 --使用 ...

  4. 软件project(六)——需求分析

           需求分析是软件开发期的第一个阶段,是关系到软件开发成败的关键步骤.需求分析的任务就是明白系统必须完毕那些工作,以下是对需求分析这一章做的简要总结. 导图: 解释说明:        我将 ...

  5. Juqery遮罩插件

    Juqery遮罩插件,想罩哪就罩哪!   一  前言 在项目开发时发现没有一个用起来 爽一点的遮罩插件,看起来觉得不难 好吧那就利用空闲时间,自己折腾一个吧,也好把jquery再温习一下, 需要的功能 ...

  6. SQL Server 后续去除功能汇总

    原文:SQL Server 后续去除功能汇总 功能更新去除汇总 字段类型 在 Microsoft SQL Server 的未来版本中将删除 ntext.text 和 image 数据类型. 请避免在新 ...

  7. WebIM(2)---消息缓存

    WebIM系列文章 在一步一步打造WebIM(1)一文中,已经介绍了如何实现一个简单的WebIM,但是,这个WebIM有一个问题,就是每一次添加消息监听器时,都必须访问一次数据库去查询是否有消息,显然 ...

  8. Unit of work + Repository

    (Unit of work + Repository) 今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository) ...

  9. win8安装tfs2010提示未启用iis6.0未启用兼容模式需要静态内容组件

    笔者的电脑由于安装TFS2010就提示这个错误,当时网上也没有很好地办法,重装iis组件也不行.如果你同样没有找到更好的办法,建议安装tfs2012,但在vs2010使用tfs2012是无法创建团队项 ...

  10. wcf跨机器访问的问题

    wcf跨机器访问的问题 在wcf跨机器的访问中遇到了各种无法访问的问题,本人也是在通过个人解决问题的基础上发表一下自己的经验,如果还有其他方面可能影响wcf跨机器的问题,还希望大家多多发言! 好了废话 ...