一步步打造一个简单的 MVC 电商网站 - BooksStore(一)
本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore
《一步步打造一个简单的 MVC 电商网站 - BooksStore(一)》
《一步步打造一个简单的 MVC 电商网站 - BooksStore(二)》
《一步步打造一个简单的 MVC 电商网站 - BooksStore(三)》
《一步步打造一个简单的 MVC 电商网站 - BooksStore(四)》
简介
主要功能与知识点如下:
分类、产品浏览、购物车、结算、CRUD(增删改查) 管理、发邮件、分页、模型绑定、认证过滤器和单元测试等(预计四篇、周五、下周一和周二)。
【备注】项目使用 VS2015 + C#6 进行开发,有问题请发表在留言区哦,还有,页面长得比较丑,请见谅。
目录
- 创建项目架构
- 创建域模型实体
- 创建单元测试
- 创建控制器与视图
- 创建分页
- 加入样式
一、创建项目架构
1.新建一个解决方案“BooksStore”,并添加以下项目:

BooksStore.Domain:类库,存放域模型和逻辑,使用 EF; BooksStore.WebUI:Web MVC 应用程序,存放视图和控制器,充当显示层,使用了 Ninject 作为 DI 容器; BoosStore.UnitTest:单元测试,对上述两个项目进行测试。
Web MVC 为一个空的 MVC 项目:

2.添加项目引用(需要使用 NuGet):



这是不同项目需要引用的类库和项目
3.设置 DI 容器
我们通过 Ninject ,创建一个自定义的工厂,一个名为NinjectControllerFactory 的类继承DefaultControllerFactory(默认的控制器工厂)。你也可以在里面添加自定义的代码,改变 MVC 框架的默认行为。

AddBindings() 添加绑定方法,先留空。
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public NinjectControllerFactory()
{
_kernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController) _kernel.Get(controllerType);
}
/// <summary>
/// 添加绑定
/// </summary>
private void AddBindings()
{
}
}
</div>
4.并且在 Global.asax 中加入一行代码,告诉 MVC 用新建的类来创建控制器对象。
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
}
</div>
二、创建域模型实体

1.在图中位置创建一个名为 Book 的实体类。
public class Book
{
/// <summary>
/// 标识
/// </summary>
public int Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 价格
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// 分类
/// </summary>
public string Category { get; set; }
}
</div>
有了实体之后,我们应该创建一个“库”对该实体进行操作,而这种持久化逻辑操作也应该和域模型是进行隔离的。
2.先定义一个接口 IbookRepository,在根目录创建一个名为 Abstract 的文件夹,顾名思义就是应该放置一些抽象的类,如接口。

public interface IBookRepository
{
IQueryable<Book> Books { get; }
}
</div>
我们通过该接口就可以得到对应类的相关信息,而不需要去管该数据如何存储,以及存储的位置,这就是存储库模式的本质。
3.接下来,我们就需要对数据库进行操作了,我们使用简单的EF(ORM 对象关系模型) 去对数据库进行操作,所以需要自己通过 Nuget 下载 EF 的类库。

4.因为之前定义了接口类,接下来就应该定义实现该接口的类了

安装完之后,再次建立一个名为 Concrete 的文件夹,存放实例。
在里面创建一个 EfDbContext 的类,派生于 DbContext,该类会为用户要使用的数据库中的每个表自动的定义一个属性。该属性名为 Books,指定了表名,DbSet<Book> 表示为 Book 实体的表模型,Book 对象相当于 Books 表中的行(记录)。
public class EfDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
}
</div>
再创建一个EfBookRepository 存储库类,它实现 IBookRepository 接口,使用了上文创建的 EfDbContext 上下文对象,包含了具体的方法定义。
public class EfBookRepository : IBookRepository
{
private readonly EfDbContext _context = new EfDbContext();
public IQueryable<Book> Books => _context.Books;
}
</div>
5.现在只差在数据库新建一张表了。
CREATE TABLE Book ( Id INT IDENTITY PRIMARY KEY, Name NVARCHAR(100), Description NVARCHAR(MAX), Price DECIMAL, Category NVARCHAR(50) )</div>
并插入测试数据:
INSERT INTO dbo.Book ( Name , Description , Price , Category ) VALUES ( N'C#从入门到精通' , -- Name - nvarchar(100) N'好书-C#从入门到精通' , -- Description - nvarchar(max) , -- Price - decimal N'.NET' -- Category - nvarchar(50) ) INSERT INTO dbo.Book ( Name , Description , Price , Category ) VALUES ( N'ASP.NET从入门到精通' , -- Name - nvarchar(100) N'好书-ASP.NET从入门到精通' , -- Description - nvarchar(max) , -- Price - decimal N'.NET' -- Category - nvarchar(50) ) INSERT INTO dbo.Book ( Name , Description , Price , Category ) VALUES ( N'多线程从入门到精通' , -- Name - nvarchar(100) N'好书-多线程从入门到精通' , -- Description - nvarchar(max) , -- Price - decimal N'.NET' -- Category - nvarchar(50) ) INSERT INTO dbo.Book ( Name , Description , Price , Catego

