zoukankan      html  css  js  c++  java
  • 《精通ASP.NET MVC5》第7章 SportStore:一个真正的应用程序(1)

    7.1 开始

    7.1.1 解决方案

    我们首先要创建的是一个空的Visual Studio solution。在这个 solution 中,我们将创建3个工程。

    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 }  

                );  

           

    完成修改后,运行你的应用,你将看到如下画面:

        

          

  • 相关阅读:
    Kubernetes 1.5部署sonarqube
    Kubernetes 1.5集成heapster
    Kubernetes 1.5 配置dashboard
    SQL SERVER中的逻辑读取,物理读取,以及预读的理解
    JS控制显示/隐藏二级菜单
    Css下拉菜单设置
    div包裹页面后多余部分没有显示,也没滚动条 overflow 属性设置
    Sql Ado.net 学习笔记之连接字符串
    Winform异步解决窗体耗时操作(Action专门用于无返回值,Func专门用于有返回值)
    SQL中的字母的大小写转换
  • 原文地址:https://www.cnblogs.com/tangge/p/6351221.html
Copyright © 2011-2022 走看看