第7章 SportsStorePeta 一个真实的应用程序

SportsStorePeta应用程序开发

步骤:

  1.创建解决方案和项目(Domain、WebUI、UnitTests)

  2.添加引用

  3.设置ID容器

  4.设计域模型

  5.创建抽象存储库

  6.创建模仿存储库

  7.添加控制器、动作及视图

  8.设置路由

  9.准备数据库及数据表

  10.创建实例框架上下文

  11.创建产品存储库

  12.添加分页

  13.改进路由及URL

  14.设置内容样式CSS

  15.创建分部视图 

一、解决方案:SportsStorePeta,该应用程序将不使用EF,而使用PetaPoco实现

  项目:

二、项目引用

  项目及依赖性

项目名 VS模板 目的 工具依赖 项目依赖 微软引用
SportsStorePeta.Domain 类库 存放域实体与逻辑,EF None None
System.Web.Mvc

System.ComponentModel.DataAnnotations

SportsStorePeta.WebUI Asp.net MVC4 应用程序  Basic(基本) 存放控制器与视图 
Ninject

Moq

SportsStorePeta.Domain None
SportsStorePeta.UnitTests  测试项目 单元测试
Ninject

Moq


SportsStorePeta.Domain

SportsStorePeta.WebUI


System.Web.Mvc

System.Web

Microsoft.CSharp

三、设置ID容器

  1.Ninject控制器工厂: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Ninject;

namespace SportsStorePeta.WebUI.Infrastructure
{
    /// <summary>
    /// 使用Ninject修改默认控制器工厂
    /// </summary>
    public class NinjectControllerFactory  :DefaultControllerFactory
    {
        private readonly 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()
        {
            //Ninject绑定
        }
    }
}

  MVC框架注册NinjectControllerFactory

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 SportsStorePeta.WebUI.Infrastructure;

namespace SportsStorePeta.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);

            //MVC框架注册NinjectControllerFactory
            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
        }
    }
}

 四、设计域模型 和视图模型

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

namespace SportsStorePeta.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; }
    }
}

      视图模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SportsStorePeta.WebUI.Models
{
    public class ProductViewModel
    {
        public int ProductId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Price { get; set; }
        public string Category { get; set; }
    }
}

五、创建抽象存储库 

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

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

六、创建模仿存储库

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 SportsStorePeta.Domain.Abstract;
using SportsStorePeta.Domain.Entities;

namespace SportsStorePeta.WebUI.Infrastructure
{
    /// <summary>
    /// 使用Ninject修改默认控制器工厂
    /// </summary>
    public class NinjectControllerFactory  :DefaultControllerFactory
    {
        private readonly 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()
        {
            //Ninject绑定
            //1.添加模拟IproductRepository实现
            Mock<IProductRepository> mock=new Mock<IProductRepository>();
            mock.Setup(m => m.Products).Returns(
                new List<Product>
                {
                    new Product {Name = "Football", Price = 35},
                    new Product {Name = "Surf board", Price = 179},
                    new Product {Name = "Running shoes", Price = 87}
                }.AsQueryable());
            //永久绑定
            _ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);
        }
    }
}

七、添加控制器、动作及视图

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStorePeta.Domain.Abstract;
using SportsStorePeta.Domain.Entities;
using SportsStorePeta.WebUI.Models;

namespace SportsStorePeta.WebUI.Controllers
{
    public class ProductController : Controller
    {
        private readonly IProductRepository _repository;

        public ProductController(IProductRepository productRepository)
        {
            _repository = productRepository;
        }

        public ViewResult List()
        {
            List<ProductViewModel> productViewModels = new List<ProductViewModel>();
            foreach (Product product in _repository.Products)
            {
                ProductViewModel productViewModel = new ProductViewModel
                {
                    ProductId = product.ProductId,
                    Name = product.Name,
                    Description = product.Description,
                    Price = product.Price,
                    Category = product.Category
                };
                productViewModels.Add(productViewModel);
            }

            return View(productViewModels);

        }
    }
}

  视图

@model IEnumerable<SportsStorePeta.WebUI.Models.ProductViewModel>
@{
    ViewBag.Title = "商品";
}

@foreach (var p in Model)
{
    <div class="item">
        <h3>@p.Name</h3>
        @p.Description
        <h4>@p.Price</h4>
    </div>
}

八、设置路由

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SportsStorePeta.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 }
            );
        }
    }
}

九、准备数据库及数据表

建表SQL语句

Create table Products(
  [ProductId] INT NOT NULL PRIMARY KEY IDENTITY,
  [Name] NVARCHAR(100) NOT NULL,
  [Description]  NVARCHAR(500) NOT NULL,
  [Category] NVARCHAR(50) NOT NULL,
  [Price] DECIMAL(16,2) NOT NULL
)

表建好后,可以插入一些数据做显示用。

INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘Lifejacket‘,N‘Protective and fashionbale‘,N‘Watersports‘,48.95);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘Soccer Ball‘,N‘FIFA-approved size and weight‘,N‘Soccer‘,19.50);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘CornerFlags‘,N‘Give your playing field a protessional ‘,N‘Soccer‘,34.50);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘蓝球‘,N‘CornerFlagssafasdfsdf‘,N‘Soccer‘,34.20);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘CornerFlags12‘,N‘CornerFlagssafasdfsdf‘,N‘Soccer‘,43.20);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘CornerFlags13‘,N‘CornerFlagssafasdfsdf‘,N‘Soccer‘,11.23);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘CornerFlags14‘,N‘CornerFlagssafasdfsdf‘,N‘Soccer‘,123.23);
INSERT INTO [Products] ([Name],[Description],[Category],[Price]) VALUES (N‘CornerFlagssafasdfsdf‘,N‘CornerFlagssafasdfsdf‘,N‘Soccer‘,32.23);

十、创建实例框架上下文

  1.NuGet中引入PetaPoco

  2.web.config添加数据库连接

 <connectionStrings>
    <add name="DbContext" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=SportsStore;Integrated Security=True" />
  </connectionStrings>

  3.设置PetaPoco,修改DataBase.tt模板

    ConnectionStringName = "DbContext";
    Namespace = "SportsStorePeta.Domain.Entities";

   修改PetaPoco.Core.ttinclude 

<#@ template language="C#" hostspecific="True" #>

  4.新建上下文类:PpDbContext

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

namespace SportsStorePeta.Domain.Concrete
{
    public class PpContext : DbContextDB
    {
        public IQueryable<Product> Products
        {
            get
            {
                var products = base.Query<Product>("Select ProductId,Name,Description,Category,Price from Products").AsQueryable();
                return products;
            }
        }
    }
}

十一、创建产品存储库PpProductRepository

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStorePeta.Domain.Abstract;
using SportsStorePeta.Domain.Entities;

namespace SportsStorePeta.Domain.Concrete
{
   public class PpProductRepository :IProductRepository
    {
       private readonly PpContext _context=new PpContext();
       public IQueryable<Product> Products
       {
           get { return _context.Products; }
       }
    }
}

  修改Ninject绑定: 

 private void AddBindings()
        {
           _ninjectKernel.Bind<IProductRepository>().To<PpProductRepository>();
        }

十二、添加分页

   修改ProductController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStorePeta.Domain.Abstract;
using SportsStorePeta.Domain.Entities;
using SportsStorePeta.WebUI.Models;

namespace SportsStorePeta.WebUI.Controllers
{
    public class ProductController : Controller
    {
        private readonly IProductRepository _repository;
        public int PageSize = 4;

        public ProductController(IProductRepository productRepository)
        {
            _repository = productRepository;
        }

        public ViewResult List(int page=1)
        {
            List<ProductViewModel> productViewModels = new List<ProductViewModel>();
            foreach (Product product in _repository.Products)
            {
                ProductViewModel productViewModel = new ProductViewModel
                {
                    ProductId = product.ProductId,
                    Name = product.Name,
                    Description = product.Description,
                    Price = product.Price,
                    Category = product.Category
                };
                productViewModels.Add(productViewModel);
            }

            return View(productViewModels.OrderBy(p => p.ProductId).Skip((page - 1)*PageSize).Take(PageSize));

        }
    }
}

  1.添加分页视图模型 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SportsStorePeta.WebUI.Models
{
    public class PageInfo
    {
        public int TotalItems { get; set; }
        public int ItemsPerPage { get; set; }
        public int CurrentPage { get; set; }

        public int TotalPages
        {
            get { return (int) Math.Ceiling((decimal) TotalItems/ItemsPerPage); }
        }
    }
}

  2.添加HTML辅助器方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using SportsStorePeta.WebUI.Models;

namespace SportsStorePeta.WebUI.HtmlHelpers
{
    public static class PagingHelpers
    {
        public static MvcHtmlString PageLinks(this HtmlHelper html, PageInfo pageInfo, Func<int, string> pageUrl)
        {
            StringBuilder result = new StringBuilder();
            for (int i = 1; i < pageInfo.TotalPages; i++)
            {
                TagBuilder tag=new TagBuilder("a");
                tag.MergeAttribute("href",pageUrl(i));
                tag.InnerHtml = i.ToString();
                if (i == pageInfo.CurrentPage)
                {
                    tag.AddCssClass("selected");
                }
                result.Append(tag.ToString());
            }
            return MvcHtmlString.Create(result.ToString());
        }
    }
}

  3.修改Views/Web.config

      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="SportsStorePeta.WebUI.HtmlHelpers"/>
      </namespaces>

  4.添加视图模型数据 ProductsListViewModel 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SportsStorePeta.WebUI.Models
{
    public class ProductsListViewModel
    {
        public IEnumerable<ProductViewModel> Products { get; set; }
        public PageInfo PagingInfo { get; set; }
    }
}

  5.更新List动作

  添加新方法处理域模型

       /// <summary>
        /// 根据Product域模型集合获得视图模型集合
        /// </summary>
        /// <param name="products"></param>
        /// <returns></returns>
        private IEnumerable<ProductViewModel> GetProductViewModelListByProducts(IQueryable<Product> products)
        {
            List<ProductViewModel> productsViewModels = new List<ProductViewModel>();
            foreach (Product product in products)
            {
                ProductViewModel productViewModel = new ProductViewModel()
                {
                    ProductId = product.ProductId,
                    Name = product.Name,
                    Category = product.Category,
                    Description = product.Description,
                    Price = product.Price.ToString("C")
                };
                productsViewModels.Add(productViewModel);
            }
            return productsViewModels;
        }
        public ViewResult List(int page=1)
        {

            ProductsListViewModel model = new ProductsListViewModel
            {
                Products = GetProductViewModelListByProducts( _repository.Products.OrderBy(p => p.ProductId).Skip((page - 1)*PageSize).Take(PageSize)),
                PagingInfo = new PageInfo { CurrentPage = page,ItemsPerPage = PageSize,TotalItems = _repository.Products.Count()}
            };

            return View(model);
        }

  6.更新List.cshtml视图

@model SportsStorePeta.WebUI.Models.ProductsListViewModel
@{
    ViewBag.Title = "商品";
}

@foreach (var p in Model.Products)
{
    <div class="item">
        <h3>@p.Name</h3>
        @p.Description
        <h4>@p.Price</h4>
    </div>
}

<div class="pager">
    @Html.PageLinks(Model.PagingInfo,x=>Url.Action("List",new{page=x}))
</div>

十三、改进路由及URL

 public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: null,
                url: "Page{page}",
                defaults: new {controller = "Product", action = "List"});

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional }
            );
        }

十四、设置内容样式CSS

  1.定义布局模板视图_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="/Content/Site.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<div id="header">
    <div class="title">体育用品</div>
</div>
<div id="categories">
    商品类别
</div>
<div id="content">
    @RenderBody()
</div>
</body>
</html>

  2.添加CSS样式

  在site.css 最下面增加:

BODY { font-family: Cambria, Georgia, "Times New Roman"; margin: 0; }
DIV#header DIV.title, DIV.item H3, DIV.item H4, DIV.pager A {
    font: bold 1em "Arial Narrow", "Franklin Gothic Medium", Arial;
}
DIV#header { background-color: #444; border-bottom: 2px solid #111; color: White; }
DIV#header div.title { font-size: 2em; padding: .6em; }
DIV#content { border-left: 2px solid gray; margin-left: 9em; padding: 1em; }
DIV#categories { float: left; width: 8em; padding: .3em; }

DIV.item { border-top: 1px dotted gray; padding-top: .7em; margin-bottom: .7em; }
DIV.item:first-child { border-top:none; padding-top: 0; }
DIV.item H3 { font-size: 1.3em; margin: 0 0 .25em 0; }
DIV.item H4 { font-size: 1.1em; margin:.4em 0 0 0; }

DIV.pager { text-align:right; border-top: 2px solid silver;
    padding: .5em 0 0 0; margin-top: 1em; }
DIV.pager A { font-size: 1.1em; color: #666; text-decoration: none;
      padding: 0 .4em 0 .4em; }
DIV.pager A:hover { background-color: Silver; }
DIV.pager A.selected { background-color: #353535; color: White; }

十五、创建分部视图 

  分部视图是嵌入在另一个视图中的一个内容片段。是自包含文件,可以跨视图重用。

  1.在Shared中添加分部视图ProductSummary.cshtml

@model SportsStorePeta.WebUI.Models.ProductViewModel

<div class="item">
    <h3>@Model.Name</h3>
    @Model.Description
    <h4>@Model.Price</h4>
</div>

  2.修改List.cshtml  

@model SportsStorePeta.WebUI.Models.ProductsListViewModel
@{
    ViewBag.Title = "商品";
}

@foreach (var p in Model.Products)
{
    Html.RenderPartial("ProductSummary",p);
}

<div class="pager">
    @Html.PageLinks(Model.PagingInfo,x=>Url.Action("List",new{page=x}))
</div>
时间: 2024-10-14 06:53:57

第7章 SportsStorePeta 一个真实的应用程序的相关文章

第7章 SportsStore 一个真实的应用程序

1.开始 解决方案:SportsStore 项目: SportsStore.Domain   //类库 //存放域实体与逻辑,EF SportsStore.WebUI   //Asp.net MVC4 应用程序  Basic(基本) //存放控制器与视图    //启动项目 SportsStore.UnitTests  //测试项目 //单元测试

第2章 Python如何运行程序

第2章 Python如何运行程序 ? 本章和下一章将快速地看一看程序的执行--你如何启动代码,以及Python如何运行它.在这一章中,我们将大体上研究一下Python解释器如何执行程序.之后的第3章将向你展示如何建立你自己的程序并运行它. ? 程序的启动细节天生就与特定的平台相关,这两章的部分内容可能并不适用于你工作的平台,所以高级读者应当随心所欲地跳过与他们预期的用途不相关的部分.同样,以往使用过类似的工具并且期望对语言快速进阶的读者可能想把这两章的部分内容束之高阁"以备日后参考".

第5章 用函数封装程序功能

第5章 用函数封装程序功能 5.1 函数就是一个大"箱子" 5.1.1 函数的声明和定义 5.1.2 函数调用机制 5.1.3 函数的声明与函数调用 5.1.4 函数参数的传递 5.1.5 函数的返回值 5.2 内联函数 5.2.1 用体积换速度的内联函数 5.2.2 内联函数的使用规则 5.3 重载函数 5.3.1 重载函数的声明 5.3.2 重载函数的解析 5.4 函数设计的基本规则 5.4.1 函数声明的设计规则 5.4.2 函数体的设计规则 TOP

Prism 文档 第二章 初始化Prism应用程序

                                                                       第二章 初始化Prism应用程序 本章将讨论为了使一个Prism应用程序的启动和运行哪些是必须的.Prism的应用程序在启动过程中需要注册和配置,这被称为引导应用程序. 什么是Bootstrapper? bootstrapper是一个类,通过Prism类库负责一个应用程序建立的初始化.通过使用bootstrapper,对于如何将Prism库组件连接到您的应

公开课视频-《第07章 部署-VMware-应用程序虚拟化-ThinApp 5.1.1》

****************** 公开课已讲课程: ****************** 2016-06-22-第04章 部署-Microsoft-服务器虚拟化-Hyper-V 2012 R22016-06-29-第05章 部署-VMware-服务器虚拟化-esxi 6.0.0 U12016-07-06-第06章 部署-VMware-桌面虚拟化-Horizon View 6.2.12016-07-13-第07章 部署-VMware-应用程序虚拟化-ThinApp 5.1.1 ********

程序是怎样跑起来的-第10章 通过汇编语言了解程序的实际构成

第10章通过汇编语言了解程序的实际构成 热身问题 1.本地代码指令中,表示其功能的英文缩写称为什么? 助记符.汇编语言是通过利用助记符来记述程序的. 2.汇编语言的源代码转换成本地代码的方式称为什么? 汇编.使用汇编器这个工具来进行汇编. 3.本地代码转换成汇编语言的源代码的方式称为什么? 反汇编.通过返汇编,得到人们可以理解的代码. 4.汇编语言的源文件的扩展名,通常是什么格式? .asm..asm是assembler(汇编器)的简称 5.汇编语言程序中的段定义指的是什么? 构成程序的命令和数

Lua_第24章 扩展你的程序

 第24章扩展你的程序 作为配置语言是 LUA的一个重要应用.在这个章节里,我们举例说明如何用 LUA 设 置一个程序.让我们用一个简单的例子开始然后展开到更复杂的应用中. 首先,让我们想象一下一个简单的配置情节:你的 C程序(程序名为 PP)有一个 窗口界面并且可以让用户指定窗口的初始大小.显然,类似这样简单的应用,有多种解决方法比使用LUA更简单,比如环境变量或者存有变量值的文件.但,即使是用一个 简单的文本文件,你也不知道如何去解析.所以,最后决定采用一个 LUA 配置文件(这就是 LUA

《Erlang程序设计》学习笔记-第6章 编译并运行程序

http://blog.csdn.net/karl_max/article/details/3976372 第6章 编译并运行程序 1. erlang:halt()可以即刻停止系统运行. 2. q()命令可以完成文件和数据库的一些处理后再退出.它是init:stop()的一个shell别名 3. erlang可以动态加载代码,正在运行的代码可以在重新编译后动态加裁而不用停止程序的运行. 4. 模块加载相关函数: code:get_path() %% 可以获取当前加载路径的设定值. code:al

【WPF学习】第二十六章 Application类——应用程序的生命周期

原文:[WPF学习]第二十六章 Application类--应用程序的生命周期 在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一.创建Application对象 使用Application类的最简单方式是手动创建它.下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序: 在本质