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. 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  2. 【BZOJ1077】天平(差分约束)

    [BZOJ1077]天平(差分约束) 题面 BZOJ 洛谷 题解 利用矩阵可以很容易得到两个点之间的最大差和最小差,再利用这个信息判断即可.差分约束用\(Floyd\)计算.时间复杂度\(O(n^3) ...

  3. 【转】#pragma的用法

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  4. bzoj1016/luogu4208 最小生成树计数 (kruskal+暴搜)

    由于有相同权值的边不超过10条的限制,所以可以暴搜 先做一遍kruskal,记录下来每个权值的边使用的数量(可以离散化一下) 可以证明,对于每个权值,所有的最小生成树中选择的数量是一样的.而且它们连成 ...

  5. 调试技巧 ------ printf 的使用技巧

    编译器宏:__FUNCTION__,__FILE__,__LINE__ #define __debug #ifdef __debug //#define debug(format,...) print ...

  6. Elasticsearch 5.0 安装 Search Guard 5 插件

    一.Search Guard 简介 Search Guard  是 Elasticsearch 的安全插件.它为后端系统(如LDAP或Kerberos)提供身份验证和授权,并向Elasticsearc ...

  7. 常用日期计算SQL语句

    -- 本月的第一天 SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) -- 本月的最后一天 SELECT DATEADD(ms,-3,DATEADD(mm ...

  8. node爬虫进阶版

    手写了一个方便爬虫的小库: const url = require('url') const glib = require('zlib') //默认头部 const _default_headers ...

  9. 什么是spu和sku

    电商概念SPU与SKU SPU = Standard Product Unit (标准产品单位)SPU是商品信息聚合的最小单位,是一组可复用.易检索的标准化信息的集合,该集合描述了一个产品的特性.通俗 ...

  10. 【转载】视频CDN技术原理与流程说明

    视频CDN专为移动互联网视频内容分发量身定做的一套自主研发的分布式平台,该平台以深圳为中心,分布在全国各地BGP机房的服务器为边缘节点,汇聚中国电信.中国联通.中国移动.中国教育网等运营商网络资源,构 ...