自强不息,厚德载物!身心自在,道法自然!


第五话 Asp.Net MVC 3.0【MVC实战项目の一】

前面几话都讲的一些有关MVC相关东西,从这话开始应用实战的项目开始。

实战一个简单的购物流程的项目吧!

首先创建一个空白的解决方案,如下图1.

图1.我们预计创建3个模块,一个模块包含我们的域模型(DoMain),一个模块包含我的MVC Web应用程序,还有一个单元测试的模块。

我们的域模型(DoMain)是一个类库项目,然后是一个Asp.Net MVC3 的Web应用程序(Razor引擎)项目,然后添加一个测试项目进来,添加测试项目如下图2.

图2.当我们创建好我们的域模型(DoMain)类库项目和测试项目(类库项目),VS会自动创建一个Class1.cs的文件和UnitTest1.cs的文件,这个对我们来说没有多大的用处,可以直接干掉。之后我们的行么如下图3.

图3.下一步就是添加项目引用,可项目需要用到包(扩展工具/第三方插件),我们项目具体要用到的第三方插件如下:

具体项目 第三插件名称
SportsStore.Domain Ninject
SportsStore.UI Ninject
SportsStore.Domain Moq
SportsStore.UI Moq             

可以在VS里面的"程序包控制管理"用下面的命令导入第三方插件包,命令如下:

Install-Package Ninject -Project SportsStore.WebUI
Install-Package Ninject -Project SportsStore.Domain
Install-Package Moq -Project SportsStore.WebUI
Install-Package Moq -Project SportsStore.Domain

也可以在相关项目上右键,使用NuGet程序包管理一个一个导入,方法根据自己所好,不在啰嗦!

然后就是我们项目的依赖关系,如下表所示:

具体项目 依赖项目
SportsStore.Domain
SportsStore.UI SportsStore.Domain
SportsStore.UnitTests

SportsStore.Domain

SportsStore.UI

因为我们将使用Ninject创建我们的MVC应用程序控制器和处理DI,所以我们需要创建一个新的类更改配置。在SportsStore.UI应用程序里创建一个文件夹(命名"Infrastructure")然后在改文件里创建一个类叫NinjectControllerFactory,它的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Ninject;
using System.Web.Routing;
using Moq;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;

namespace SportsStore.WebUI.Infrastructure
{
    public class NinjectControllerFactory : DefaultControllerFactory
    {
        private IKernel ninjectKernel;

        public NinjectControllerFactory() 
        {
            this.ninjectKernel = new StandardKernel();
            AddBindings();
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
        }

        private void AddBindings()
        {
            //绑定额外数据
        }
    }
}

我们需要注册NinjectControllerFactory到MVC框架,所以我们也需要在Global.asax.cs里给它注册进去,具体代码如下:

     protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            //注册路由
            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
        }

我们可以试着启动跑下我的MVC Web项目,结果如下图4.

图4.如果真出现这个错误页面也是预计必然的结果,接下来的任务就是让这个页面消失吧!

从我们的域模型(DoMain)开始吧!既然我们搞的是一个购物流程的项目,那我们肯定需要商品才能购物,那就在域模型(Domain)里创建一个文件夹(命名"Entities")放相应的模型在该文件夹来创建一个Product类吧!Product类的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SportsStore.Domain.Entities
{
    public class Product : Object
    {
        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; }
    }
}

接下来创建一个抽象存储库,我们知道我们用一些方法可以是Prodcut和数据交互,这里我们使用存储库模式,我们不需要担心他是如何去实现,所以在域模型(DoMain)项目里建立一个文件夹(命名"Abstract")在该文件里创建一个接口"IProductRepository",它的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Abstract
{
    public interface IProductRepository
    {
        IQueryable<Product> Products { get; }
    }
}

这个接口使用这个IQueryable < T >可以获取Product对象,它没有说任何关于如何或数据存储在哪里或者它将如何被检索。一个类,它使用IProductRepository接口就可以获得Product对象,但是不需要知道任何关于它们来自于哪儿,或者他们如何将被交付到那儿,这是最基本的存储库的模式。

然后我们使用模拟库,因为我们一定定义了一个接口那么我接着就实现它,让他跟数据交互,我们模拟一下实现IProductRepository接口,代码如下:

        private void AddBindings()
        {
            //绑定额外数据
            //模拟IProductRepository实现
            Mock<IProductRepository> mock = new Mock<IProductRepository>();
            mock.Setup(h => h.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());
            this.ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);
        }

准备工作的差不多了我们需要要能展现的东西出来才不算前功尽弃,我们要展示出我们的商品,首先要来创建相应的控制器(命名"ProductController"),代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;

namespace SportsStore.WebUI.Controllers
{
    public class ProductController : Controller
    {
        private IProductRepository repository;
        public ProductController(IProductRepository productReposittory) 
        {
            this.repository = productReposittory;
        }
    }
}

这个只不过是一个的空的控制器,我们创建了一个构造函数,该函数接收IProductRepository来的参数,这里也就方便Ninject在Product对象实例化的时候的注入(构造注入)。然后我需要返回一个视图展示出来,所以修改ProductController控制器如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;

namespace SportsStore.WebUI.Controllers
{
    public class ProductController : Controller
    {
        private IProductRepository repository;
        public ProductController(IProductRepository productReposittory) 
        {
            this.repository = productReposittory;
        }
        //返回一个视图
        public ViewResult List()
        {
            return this.View(this.repository.Products);
        }
    }
}

接下来,需要添加一个视图(View),我们需要创建一个强类型视图,如下图5.

图5.当然在我们选择模型类的时候,下拉框并不能找到IEnumerable<SportsStore.Domain.Entities.Product>,因为他不会包含枚举的域模型(DoMain)对象,所以需要我们手动输入。

IEnumerable<Product>意味着我们可以创建一个列表,现在就用犀利Razor引擎来搞这个页面,List.cshtml页面代码如下:

@model IEnumerable<SportsStore.Domain.Entities.Product>

@{
    ViewBag.Title = "Product List";
}
@foreach (var Product in Model)
{
    <div class="item">
    <h3>@Product.Name</h3>
    @Product.Description
    <h4>@Product.Price.ToString("C")</h4>
    </div>
}

说明:@Product.Price.ToString("C"),ToString("C")根据你的服务器将数字转换为相应的货币。

然后我们需要修改一下默认的路由,具体的修改如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
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
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // 路由名称
                "{controller}/{action}/{id}", // 带有参数的 URL
                new { controller = "Product", action = "List", id = UrlParameter.Optional } // 参数默认值
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            //注册路由
            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
        }
    }
}

注明:修改就是上面代码红色部分里标识为蓝色的控制器名称和相应方法(Action)名称。

接下来,在跑下我们的MVC Web应用程序,运行结果如下图6所示.

图6.可以看到我们已经消灭之前的黄页了,项目开始就先搞怎么些东西,后续继续完善。要是那里描述有误还请路过的前辈牛人给点指点,这样才能更好的进步,谢谢!

posted @ 2012-07-04 18:00  辉太  阅读(6451)  评论(14编辑  收藏  举报

路漫漫其修远兮,吾将上下而求索!