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)的更多相关文章

  1. ASP.NET + MVC5 入门完整教程八 -—-- 一个完整的应用程序(上)

    https://blog.csdn.net/qq_21419015/article/details/80509513 SportsStore 1.开始创建Visual Studio 解决方案和项目这里 ...

  2. ASP.NET + MVC5 入门完整教程八 -—-- 一个完整的应用程序(下)

    https://blog.csdn.net/qq_21419015/article/details/80802931 SportsStore 1.导航 添加导航控件 如果客户能够通过产品列表进行分类导 ...

  3. ASP.NET MVC5 第4章

    参考资料<ASP.NET MVC5 高级编程>第5版 第4章 模型 本章所探讨的模型是要显示.保存.创建.更新和删除的对象. 基架指使用 MVC 提供的工具为每个模型对象的标准索引构建.创 ...

  4. 第一个 MVC 应用程序(上半部分)(《精通 ASP.NET MVC5》 的第二章)

    本章将使用 ASP.NET MVC 框架创建一个简单的数据录入应用程序. 笔者会将过程分解成一个个的步骤,以便能够看出如何构造 ASP.NET MVC 应用程序.(对于一些未进行解释的内容,笔者提供了 ...

  5. 《精通ASP.NET MVC5》第2章 第一个MVC应用程序

      控制器     public class NewHomeController : Controller     {         // GET: /NewHome/         public ...

  6. ASP.NET MVC5(一)—— URL路由

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  7. Asp.Net MVC5入门学习系列③

    原文:Asp.Net MVC5入门学习系列③ 添加一个视图(View) 接着上篇的入门系列,上面解说添加一个简单Controller(控制器),这里我们简单的在来添加一个View(视图)来展示我们Co ...

  8. Asp.Net MVC5入门学习系列②

    原文:Asp.Net MVC5入门学习系列② 添加一个Controller(控制器) 因为我们用的是Asp.Net MVC,MVC最终还是一套框架,所以我们还是需要遵循它才能玩下去,或者说是更好的利用 ...

  9. ASP.NET MVC5 高级编程 第5章 表单和HTML辅助方法

    参考资料<ASP.NET MVC5 高级编程>第5版 第5章 表单和HTML辅助方法 5.1 表单的使用 5.1.1 action 和 method 特性 默认情况下,表单发送的是 HTT ...

随机推荐

  1. maven使用阿里镜像配置文件

    方法一: apache-maven-3.5.2\confsetting.xml,添加如下镜像配置: <mirrors> <mirror> <id>alimaven& ...

  2. 一本通1645Fibonacci

    1645:Fibonacci 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 原题来自:POJ 3070 我们知道斐波那契数列 F0=0,F1=1,Fn=Fn ...

  3. 洛谷U19464 山村游历(Wander)(LCT)

    洛谷题目传送门 LCT维护子树信息常见套路详见我的总结 闲话 题目摘自WC模拟试题(by Philipsweng),原题目名Wander,"山村游历"是自己搞出来的中文名. 数据自 ...

  4. 【bzoj3932】 CQOI2015—任务查询系统

    http://www.lydsy.com/JudgeOnline/problem.php?id=3932 (题目链接) 题意 给出$m$个区间,每个区间有一个权值,$n$组询问,每次询问在位置$x$权 ...

  5. [八省联考2018]林克卡特树lct——WQS二分

    [八省联考2018]林克卡特树lct 一看这种题就不是lct... 除了直径好拿分,别的都难做. 所以必须转化 突破口在于:连“0”边 对于k=0,我们求直径 k=1,对于(p,q)一定是从p出发,走 ...

  6. 置换群和Burnside引理,Polya定理

    定义简化版: 置换,就是一个1~n的排列,是一个1~n排列对1~n的映射 置换群,所有的置换的集合. 经常会遇到求本质不同的构造,如旋转不同构,翻转交换不同构等. 不动点:一个置换中,置换后和置换前没 ...

  7. 【codevs1065】01字符串

    题目大意:输出仅由 0 和 1 组成的长度为 N 的字符串个数,并且其中不能含有 3 个连续的相同子串. 题解:数据太水,正规解法应该是枚举后缀进行判断. 代码如下 #include <bits ...

  8. 实战:使用SVN+apache搭建一个版本控制服务器

    今天讲的内容: 实战:使用SVN+apache搭建一个版本控制服务器 每天: 10:00 晚上:21:00 服务端:xuegod63.cn   IP:192.168.10.63 服务概述: SVN(s ...

  9. Kubernetes Service

    目录 基本概念 服务发现与负载均衡 配置Service 创建一个ClusterIP类型的Service 创建一个指定ClusterIP的Service 创建一个headless service 创建一 ...

  10. Linux 之 crontab 使用

    定时任务 任务调度的crond常驻命令crond 是linux用来定期执行程序的命令.当安装完成操作系统之后,默认便会启动此任务调度命令.crond命令每分锺会定期检查是否有要执行的工作,如果有要执行 ...