《精通ASP.NET MVC5》第7章 SportStore:一个真正的应用程序(1)
7.1 开始
7.1.1 解决方案
个工程。
1. 一个域模块工程。
2.一个MVC4应用。
3.一个单元测试工程。
现在我们就创建一个名为
SportsStore
的空 solution ,
|
工程名 |
VS工程模板 |
目的 |
|
SportsStore.Domain |
Class Library |
使用Entity Framework 创建一个repository,并将其设置为一个持久层。 |
|
SportsStore.WebUI |
ASP.NET MVC Web Application |
controllers and views |
|
SportsStore.UnitTests |
Unit Test Project |
unit tests |

7.1.2 安装工具包
Install-Package Ninject -version 3.0.1.10
Install-Package Ninject.Web.Common -version 3.0.0.7
Install-Package Ninject.MVC3 -Version 3.0.0.6
Install-Package Moq -version 4.1.1309.1617
Install-Package Microsoft.Aspnet.Mvc -version 5.0.0
7.1.3 项目之间的引用
到这一步我们的项目框架的雏形已经出来了,现在我们要为它添加引用。在solusion管理器中,一次右击
每个工程,选择Add Reference。
|
工程名 |
工具依赖 |
工程依赖 |
微软引用 |
|
SportsStore.Domain |
Entity Framework |
None |
System.Web.Mvc System.ComponentModel.DataAnnotations |
|
SportsStore.WebUI |
Ninject Moq |
SportsStore.Domain
|
None |
|
SportsStore.UnitTests |
Ninject Moq |
SportsStore.Domain SportsStore.WebUI |
System.Web.Mvc System.Web Microsoft.CSharp |
注意:
System.Web.Mvc 的版本一定选择4.0.0
7.1.4 设置DI Container
在我们这个应用中,对MVC框架做了很多扩展,这也是我们学习的重点内容,掌握了这些知识点,
我们再以后的开发项目中,就能得心应手,构建出稳定的,易于扩展和维护的企业应用架构。
右击
SportsStore.WebUI 工程的 Infrastructure 文件夹,选择添加类,类名为 NinjectControllerFactory ,
|
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace SportStore.WebUI.Infrastructure { /// <summary> /// 工厂类 /// </summary> public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { //put bindings here } } } |
我们现在还没有添加任何绑定,但是,当我们需要时,能使用 AddBindings 方法去添加. 现在,我们需要去
告诉 MVC 我们打算使用 NinjectController 类去创建Controller对象,要实现这一点,请打开SportsStore.WebUI工程的 Global.asax.cs 文件
|
public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); //我们需要告诉我们想要使用 Ninject Controller MVC //类来创建控制器对象 ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); } } |
7.2 启动域模块
现在我们将要启动域模块,在MVC应用中应用领域模型,能使每一件事情都变得完美,因此,域 也就必然 是启动应用的最完美的地方。因为我们要做的电子商务应用,所以,我们需要一个产品,这是在明显不过的事了。右击我们刚刚建立的 Entities 文件夹,然后新建一个C#类,命名为 Product
|
namespace SportStore.Domain.Entities { public class Product { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { get; set; } } } |
7.2.1 创建抽象存储库
我们知道,我们需要一些途径或方式,去数据库中取得Product entities。为了保持架构上的完美,我们要遵循持久逻辑与域模型实体分离的原则,要做到这一点,我们使用repository 设计模式. 我们不需要担心怎样去实现持久层,我们从定义一个接口开始,去启动它。
在 Abstract 文件夹上右击,选择添加一个接口,命名为
IProductsRepository ,
|
namespace SportStore.Domain.Abstract { public interface IProductRepository { IEnumerable<Product> Products { get; } } } |
这个接口使用了 IEnumerable<T> 接口去获取一个Product对象,我们没有告诉它去哪或怎么样去取得数据,一个使用 IProductsRepository
接口的类能够取得Product 对象,而不需要知道它们从哪来或被谁传递,这就是 repository设计模式的本质。接下来我们就通过添加一些特性到我们代码中,去再次拜访一下这个接口。
7.2.2 创建模仿存储库
构建一个Mock Repository
现在我们已经定义了一个 abstract interface, 我们能够实现这个持久化机制并且挂接到数据库,不过这是不是现在要做的,为了能够启动这个项目的其他部分,现在我们要创建一个 IProductsRepository
接口的 Mock
实现,我们需要在我们的 SportsStore.WebUI 工程的 NinjectControllerFactory
类的 AddBindings
方法中去做这件事。
|
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using Moq; using Ninject; using SportStore.Domain.Abstract; using SportStore.Domain.Entities; namespace SportStore.WebUI.Infrastructure { /// <summary> /// 工厂类 /// </summary> public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { //告诉Moq想使用哪种模仿对象 Mock<IProductRepository> mock = new Mock<IProductRepository>(); //Setup 给模仿对象添加一个方法 //Returns 调用模仿方法时 Moq 返回的结果 mock.Setup(m => m.Products).Returns(new List<Product> { new Product { Name = "Football", Price = 25 }, new Product { Name = "Surf board", Price = 179 }, new Product { Name = "Running shoes", Price = 95 } }); //ToConstant 表示,应该将服务绑定到指定的常数值。 ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object); //put bindings here } } } |
无论 IProductsRepository 在哪获得了一个请求, 我们都需要
Ninject
去返回同样的 mock 对象,这就是 为什么我们使用 ToConstant 方法的原因。
...
ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);
7.3 显示产品列表
7.3.1 添加控制器
已经做了这么久,我们还没有看到任何可视化的效果,这对于有些心急的朋友来说是不公平的,看不见有任何成绩出来,将会打击我们做项目的信心,这对开发团队是很不利的事情,现在就让我们添加一个Controller
到
SportsStore.WebUI
工程中,选择添加控制器,命名为
ProductController,确保模板选型为空,如下图:

接下来,你要删除VS自动为你添加的代码,并用如下代码代替:
|
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using SportStore.Domain.Abstract; namespace SportStore.WebUI.Controllers { public class ProductController : Controller { private IProductRepository repository; public ProductController(IProductRepository productRepository) { this.repository = productRepository; } public ViewResult List() { return View(repository.Products); } } } |
7.3.2 添加视图
现在要做的是添加一个View,在 List 方法上右击并选择添加View,如图:

这里请注意了,在模型类的下拉列表中,你并不能找到
IEnumerable<SportsStore.Domain.Entities.Product> 项,你需要手工输入它。然后,点击添加按钮,创建View。
渲染View数据
|
@model IEnumerable<SportsStore.Domain.Entities.Product> @{ ViewBag.Title = "Products"; } @foreach (var p in Model) { <div class="item"> <h3>@p.Name</h3> @p.Description <h4>@p.Price.ToString("c")</h4> </div> } |
我们改变一下这个页的标题,注意这里我们不需要使用
Razor text 或者
@:elements
去展示数据,因为每行内容都是一个
HTML 元素.
7.3.3 设置默认路由
现在我们需要去做的,就是告诉MVC框架,当一个请求到达时,我们的网站要映射到ProductController类的List 活动方法,这需要去修改App_Start/RouteConfig.cs
文件的
RegisterRoutes 方法,
|
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional } ); |
完成修改后,运行你的应用,你将看到如下画面:
|
|
《精通ASP.NET MVC5》第7章 SportStore:一个真正的应用程序(1)的更多相关文章
- ASP.NET + MVC5 入门完整教程八 -—-- 一个完整的应用程序(上)
https://blog.csdn.net/qq_21419015/article/details/80509513 SportsStore 1.开始创建Visual Studio 解决方案和项目这里 ...
- ASP.NET + MVC5 入门完整教程八 -—-- 一个完整的应用程序(下)
https://blog.csdn.net/qq_21419015/article/details/80802931 SportsStore 1.导航 添加导航控件 如果客户能够通过产品列表进行分类导 ...
- ASP.NET MVC5 第4章
参考资料<ASP.NET MVC5 高级编程>第5版 第4章 模型 本章所探讨的模型是要显示.保存.创建.更新和删除的对象. 基架指使用 MVC 提供的工具为每个模型对象的标准索引构建.创 ...
- 第一个 MVC 应用程序(上半部分)(《精通 ASP.NET MVC5》 的第二章)
本章将使用 ASP.NET MVC 框架创建一个简单的数据录入应用程序. 笔者会将过程分解成一个个的步骤,以便能够看出如何构造 ASP.NET MVC 应用程序.(对于一些未进行解释的内容,笔者提供了 ...
- 《精通ASP.NET MVC5》第2章 第一个MVC应用程序
控制器 public class NewHomeController : Controller { // GET: /NewHome/ public ...
- ASP.NET MVC5(一)—— URL路由
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- Asp.Net MVC5入门学习系列③
原文:Asp.Net MVC5入门学习系列③ 添加一个视图(View) 接着上篇的入门系列,上面解说添加一个简单Controller(控制器),这里我们简单的在来添加一个View(视图)来展示我们Co ...
- Asp.Net MVC5入门学习系列②
原文:Asp.Net MVC5入门学习系列② 添加一个Controller(控制器) 因为我们用的是Asp.Net MVC,MVC最终还是一套框架,所以我们还是需要遵循它才能玩下去,或者说是更好的利用 ...
- ASP.NET MVC5 高级编程 第5章 表单和HTML辅助方法
参考资料<ASP.NET MVC5 高级编程>第5版 第5章 表单和HTML辅助方法 5.1 表单的使用 5.1.1 action 和 method 特性 默认情况下,表单发送的是 HTT ...
随机推荐
- 洛谷P4831 Scarlet loves WenHuaKe
这道题告诉我们推式子的时候头要够铁. 题意 问一个\(n\times m\)的棋盘,摆上\(n\times 2\)个中国象棋的炮使其两两不能攻击的方案数,对\(998244353\)取模. \((n\ ...
- SECD machine
SECD machine 对程序语言理论的理解 程序语言理论主要研究语法.语义及语言的实现.编程语言有语法,各种数学逻辑.结构化数据都有语法.乔姆斯基的语言体系及巴科斯范式是语法分析的基础,语法分析将 ...
- (转)CS0016: 未能写入输出文件
转自:http://www.pageadmin.net/article/20130305/537.html 编译错误 说明: 在编译向该请求提供服务所需资源的过程中出现错误.请检查下列特定错误详细信息 ...
- System.gc()与Runtime.gc()的区别
(1) GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象 ...
- BZOJ 4764: 弹飞大爷
4764: 弹飞大爷 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 4 Solved: 4[Submit][Status][Discuss] Des ...
- Strassen矩阵乘法之思考
可不可以有另外的划分小矩阵的方法? A*B=C A/B分成n*m个矩阵 可看成一个多元方程. Ci,k = Ai,j * Bjk 每一个Ci,k看成方程的一个未知数 每一个小式子:对于A或B同一列/行 ...
- sort与qsort的区别与联系
sort属于C++范畴,在algorithm头文件中,下面直奔主题,给大家一个清晰明了的认识.qsort有C,和C++两个版本. qsort的compare函数原型 //comp ,也就说,如果the ...
- 移动端Web页面问题解决方案
1.安卓浏览器看背景图片,有些设备会模糊. 用同等比例的图片在PC机上很清楚,但是手机上很模糊,原因是什么呢? 经过研究,是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率来显 ...
- react入门-组件方法、数据和生命周期
react组件也像vue一样,有data和methods,但是写法就很不同了: <!DOCTYPE html> <html lang="en"> <h ...
- SQL记录-PLSQL面向对象
PL/SQL面向对象 PL/SQL允许定义一个对象类型,这有助于在Oracle的数据库中设计的面向对象.对象类型可以包装复合类型.使用对象允许实现数据的具体结构现实世界中的对象和方法操作它.对象有属性 ...
