• 使用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数据操作的风采。如果你觉得我写的辛苦,你觉得你得到了你想要的东西,那么请推荐它给其他有需要的人吧!请继续关注我的续篇,精彩才刚刚开始!
  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3113340.html
Copyright © 2020-2023  润新知