zoukankan      html  css  js  c++  java
  • 使用MVC4,Ninject,EF,Moq,构建一个真实的应用电子商务SportsStore

     

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

    如果你已经准备好了开始MVC4的远航,那我们就闲话少说,背起行装,踏上征途吧!
     
    完成SportsStore电子商务平台,你将学会:
    1.使用MVC4开发你的应用项目.
    2.使用Ninject完成IOC注入.
    3.使用Entity Framework 操作Sql server 数据库.
    4.使用Moq测试你的项目。
     
    好了,现在请启动你的VS2012吧!
     
    我们首先要创建的是一个空的Visual Studio solution。在这个solution中,我们将创建3个工程。
    1. 一个域模块工程。
    2.一个MVC4应用。
    3.一个单元测试工程。
     
    现在我们就创建一个名为SportsStore的空solution,它看起来像下面的截图:
     
     

    工程名

    VS工程模板

    目的

    SportsStore.Domain

    Class Library

    域Entities和logic;

    使用Entity Framework 创建一个repository,并将其设置为一个持久层。

    SportsStore.WebUI

    ASP.NET MVC 4 Web Application

    controllers and views

    SportsStore.UnitTests

    Unit Test Project

    unit tests

     
    你可以删除SportsStore.Domain工程中的class1.cs,我们不会使用它。
    在SportsStore.Domain建两个文件夹Abstract,Entities. 在SportsStore.WebUI中建一个文件夹Infrastructure. 如下图:
     
     
     
    到这一步我们的项目框架的雏形已经出来了,现在我们要为它添加引用。在solusion管理器中,一次右击
    每个工程,选择Add Reference。

    工程名

    工具依赖

    工程依赖

    微软引用

    SportsStore.Domain

    None

    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
     
    设置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;
    using SportsStore.Domain.Abstract;
    using SportsStore.Domain.Entities;
    using Moq;
    using Ninject;
     
    namespace SportsStore.WebUI.Infrastructure
    {
        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 class 去创建Controller对象,要实现这一点,请打开SportsStore.WebUI工程的Global.asax.cs 文件,添加代码:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    using System.Web.Mvc;
    using System.Web.Optimization;
    using System.Web.Routing;
    using SportsStore.WebUI.Infrastructure;
     
    namespace SportsStore.WebUI
    {
        // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
        // 请访问 http://go.microsoft.com/?LinkId=9394801
     
        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
     
                WebApiConfig.Register(GlobalConfiguration.Configuration);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
     
                //Added by wangzhiyue 
                ControllerBuilder.Current.SetControllerFactory(new
                             NinjectControllerFactory());
                //Added end
     
                AuthConfig.RegisterAuth();
            }
        }
    }
     
    启动域模块
     
    现在我们将要启动域模块,在MVC应用中应用领域模型,能使每一件事情都变得完美,因此,域 也就必然 是启动应用的最完美的地方。因为我们要做的电子商务应用,所以,我们需要一个产品,这是在明显不过的事了。右击我们刚刚建立的Entities文件夹,然后新建一个C#类,命名为Product ,代码如下:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace SportsStore.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; }
        }
    }
     
    注意这个public关键字,因为我们将域模型分离为独立的工程,所以将访问关键字定义为public,你可以不
    这么做,但这样做有助于模块的分离,使项目层次鲜明、简洁。
     
     如果你觉得从我的文章中学到了知识,那么请继续关注我续篇!
     
     
     
    标签: MVC4NinjectEFMoqasp.netC#IOC

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

    上一篇中,我们建立了一个基本的项目框架,如果你细心的去研究这个框架,你一定已经发现,我们实际上已经使用了一个领域模型代替了MVC中的model,为什么要这么做呢?只要是因为在MVC这个古老的三层架构中,M的本意是用来向Controller提供数据,封装业务逻辑的,C在通过调用View来展示数据给用户。反过来,用户通过触发View的某些事件来将自己的意图传递给C,C再分发用户的命令道M,去获取用户想要的结果。这是一种理想的状态,在真正的项目中,经常会出现M绕过C,直接调用V,而View也会直接调用M的现象。这就导致了一种错误的、混乱的数据流的出现,是项目潜在风险递增的根源。MVP就是为了克服这种现象而产生的,好了,我们不去管什么MVP,MVVM了,现在就 言归正传,回到我们的项目中,继续展示MVC的精彩与魅力。
     
    我们知道,我们需要一些途径或方式,去数据库中取得Product entities。为了保持架构上的完美,我们要遵循持久逻辑与域模型实体分离的原则,要做到这一点,我们使用repository 设计模式. 我们不需要担心怎样去实现持久层,我们从定义一个接口开始,去启动它。
     
    在Abstract文件夹上右击,选择添加一个接口,命名为IProductsRepository,代码如下:
    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using SportsStore.Domain.Entities;
    
    namespace SportsStore.Domain.Abstract
    {
        public interface IProductsRepository
        {
            IQueryable<Product> Products { get; }
        }
    }
    复制代码

    这个借口使用了IQueryable<T>接口去获取一个Product对象,我们没有告诉它去哪或怎么样去取得数据,一个使用IProductsRepository 接口的类能够取得Product 对象,而不需要知道它们从哪来或被谁传递,这就是 repository设计模式的本质。接下来我们就通过添加一些特性到我们代码中,去再次拜访一下这个接口。
     
    构建一个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 SportsStore.Domain.Abstract;
    using SportsStore.Domain.Entities;
    using Moq;
    using Ninject;
     
    namespace SportsStore.WebUI.Infrastructure
    {
        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() {
     
                    Mock<IProductsRepository> mock = new Mock<IProductsRepository>();
     
                    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 }
                    }.AsQueryable());
                    ninjectKernel.Bind<IProductsRepository>().ToConstant(mock.Object);
                }
             }
        }
     
    为了使这些添加的代码能够正常的运行,需要添加几个命名空间,但是我们创建Mock repository实现的过程使用了Moq技术,AsQueryable 方法是一个 LINQ 扩展方法,它转换IEnumerable<T>进入
    IQueryable<T>, 这里我们需要去匹配我们的接口签名。无论 IProductsRepository在哪获得了一个请求, 我们都需要Ninject去返回同样的mock对象,这就是 为什么我们使用ToConstant方法的原因。
    ...
    ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);
    ...
     
    展示产品列表
     
    已经做了这么久,我们还没有看到任何可视化的效果,这对于有些心急的朋友来说是不公平的,看不见有任何成绩出来,将会打击我们做项目的信心,这对开发团队是很不利的事情,现在就让我们添加一个Controller到
    SportsStore.WebUI工程中,选择添加控制器,命名为ProductController,确保模板选型为空,如下图:
     
     
    接下来,你要删除VS自动为你添加的代码,并用如下代码代替:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using SportsStore.Domain.Abstract;
    using SportsStore.Domain.Entities;
     
    namespace SportsStore.WebUI.Controllers
    {
        public class ProductController : Controller
        {
            private IProductsRepository repository;
            public ProductController(IProductsRepository productRepository)
            {
                this.repository = productRepository;
            }
     
            public ViewResult List()
            {
                return View(repository.Products);
            }
     
        }
    }
     
    如果你的工程中,using SportsStore.Domain.Abstract; 这条语句存在错误,你需要添加对SportsStore.Domain工程的引用,如下图:
     
    现在要做的是添加一个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 元素.
     
    设置Default Route
     
    现在我们需要去做的,就是告诉MVC框架,当一个请求到达时,我们的网站要映射到 
    ProductController类的List 活动方法,这需要去修改
    App_Start/RouteConfig.cs文件的
     
    RegisterRoutes方法,代码如下:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
     
    namespace SportsStore.WebUI
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
     
                routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional }
                );
            }
        }
    }
     
    完成修改后,运行你的应用,你将看到如下画面:
     
     
    你可以去下载我的源码,地址是:
     
    这部分我们展示了我们应用,运用了部分Moq技术和Ninject技术,但是我们现在的数据还只是Mock对象中的模拟数据,还不是真正的数据库中的数据,下一部分,我们将引入EF框架,去领略一下ORM数据操作的风采。如果你觉得我写的辛苦,你觉得你得到了你想要的东西,那么请推荐它给其他有需要的人吧!请继续关注我的续篇,精彩才刚刚开始!
  • 相关阅读:
    回顾python,就当做笔记了
    测试知识回顾
    转发 Python接口自动化
    性能测试脚本调优
    java
    新的一年,希望自己有所提升,在这简单的记录,自己的学习。
    navicat 连接 mysql 出现Client does not support authentication protocol requested by server解决方案
    tomcat context配置
    tomcat host 配置
    flyway使用
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3113340.html
Copyright © 2011-2022 走看看