您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

打造一个简单的 MVC 电商网站 (一)

2023/9/28 11:34:11发布19次查看
简介
主要功能与知识点如下:
分类、产品浏览、购物车、结算、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); } /// /// 添加绑定 /// private void addbindings() { } }
4.并且在 global.asax 中加入一行代码,告诉 mvc 用新建的类来创建控制器对象。
controllerbuilder.current.setcontrollerfactory(new ninjectcontrollerfactory());
global.asax
二、创建域模型实体
1.在图中位置创建一个名为 book 的实体类。
public class book { /// /// 标识 /// public int id { get; set; } /// /// 名称 /// public string name { get; set; } /// /// 描述 /// public string description { get; set; } /// /// 价格 /// public decimal price { get; set; } /// /// 分类 /// public string category { get; set; } }
有了实体之后,我们应该创建一个“库”对该实体进行操作,而这种持久化逻辑操作也应该和域模型是进行隔离的。
2.先定义一个接口 ibookrepository,在根目录创建一个名为 abstract 的文件夹,顾名思义就是应该放置一些抽象的类,如接口。
public interface ibookrepository { iqueryable books { get; } }
我们通过该接口就可以得到对应类的相关信息,而不需要去管该数据如何存储,以及存储的位置,这就是存储库模式的本质。
3.接下来,我们就需要对数据库进行操作了,我们使用简单的ef(orm 对象关系模型) 去对数据库进行操作,所以需要自己通过 nuget 下载 ef 的类库。
4.因为之前定义了接口类,接下来就应该定义实现该接口的类了
安装完之后,再次建立一个名为 concrete 的文件夹,存放实例。
在里面创建一个 efdbcontext 的类,派生于 dbcontext,该类会为用户要使用的数据库中的每个表自动的定义一个属性。该属性名为 books,指定了表名,dbset 表示为 book 实体的表模型,book 对象相当于 books 表中的行(记录)。
public class efdbcontext : dbcontext { public dbset books { get; set; } }
再创建一个efbookrepository 存储库类,它实现 ibookrepository 接口,使用了上文创建的 efdbcontext 上下文对象,包含了具体的方法定义。
public class efbookrepository : ibookrepository { private readonly efdbcontext _context = new efdbcontext(); public iqueryable books => _context.books; }
5.现在只差在数据库新建一张表了。
create table book ( id int identity primary key, name nvarchar(100), description nvarchar(max), price decimal, category nvarchar(50) )
并插入测试数据:
测试数据
因为我希望表名为 book,而不是 books,所以我在之前的 book 类上加上特性 [table(book)]:
三、创建单元测试
1.做完预热操作后,你可能想立即以界面的的方式进行显示,别急,先用单元测试检查一下我们对数据库的操作是否正常,通过对数据进行简单的读取,检查下连接是否成功。
2.单元测试也需要引入 ef 类库(nuget)。
3.安装完之后会生成一个 app.config 配置文件,需要额外添加一行连接字符串(在后续的 web ui 项目里,也需要加上这条信息,不然会提示对应的错误信息)。
4.当所有前置工作都准备好了的时候,就应该填写测试方法了,因为我插入了 7 条数据,这里我就判断一下从数据库读取出的行数是否为 7 :
[testmethod] public void bookscounttest() { var bookrepository=new efbookrepository(); var books = bookrepository.books; assert.areequal(books.count(),7); }
5.在该方法体的内部单击右键,你可以看到一个“运行测试”的选项,这时你可以尝试单击它:
从这个符号可以看到,是成功了!
接下来,我们要正式从页面显示我们想要的信息了。
四、创建控制器与视图 
1.先新建一个空的控制器:bookcontroller:
2.需要我们自定义一个 details 方法,用于后续与界面进行交互。
public class bookcontroller : controller { private readonly ibookrepository _bookrepository; public bookcontroller(ibookrepository bookrepository) { _bookrepository = bookrepository; } /// /// 详情 /// /// public actionresult details() { return view(_bookrepository.books); } }
3.接下来,要创建一个视图 view 了。
4.将 details.cshtml 的内容替换为下面的:
@model ienumerable@{ viewbag.title = books; } @foreach (var item in model) { @item.name@item.description@item.price.tostring(c)
}
5.改下默认的路由机制,让他默认跳转到该页面。
6.还有一点需要注意的是,因为我们使用了 ninject 容器,并且需要对控制器中的构造函数中的参数ibookrepository 进行解析,告诉他将使用哪个对象对该接口进行服务,也就是需要修改之前的 addbindings 方法:
7.运行的效果大致如下(因为加了点 css 样式,所以显示的效果可能有些许不同),结果是一致的。
五、创建分页
1.在 models 文件夹新增一个 paginginfo.cs 分页信息类。
/// /// 分页信息 /// public class paginginfo { /// /// 总数 /// public int totalitems { get; set; } /// /// 页容量 /// public int pagesize { get; set; } /// /// 当前页 /// public int pageindex { get; set; } /// /// 总页数 /// public int totalpages => (int)math.ceiling((decimal)totalitems / pagesize); }
2.新增一个 htmlhelpers 文件夹存放一个基于 html 帮助类的扩展方法:
public static class paginghelper { /// /// 分页 /// //////////// public static mvchtmlstring pagelinks(this htmlhelper helper, paginginfo paginginfo, func func) { var sb = new stringbuilder(); for (var i = 1; i x.id).skip((pageindex - 1) * pagesize).take(pagesize), pagesize = pagesize, pageindex = pageindex, totalitems = _bookrepository.books.count() }; return view(model); } }
5.修改视图模型后,对应的视图页也需要修改
@model wen.booksstore.webui.models.bookdetailsviewmodels @{ viewbag.title = books; } @foreach (var item in model.books) { @item.name@item.description@item.price.tostring(c)
} @html.pagelinks(model, x => url.action(details, new { pageindex = x }))
六、加入样式
1.页面的样式简单的设计为 3 大板块,顶部为标题,左侧边栏为分类,主模块将显示具体内容。
我们现在要在 views 文件夹下创建一个文件 _viewstart.cshtml,再创建一个 shared 的文件夹和文件 _layout.cshtml。
2._layout.cshtml 这是布局页,当代码执行到 @renderbody() 时,就会负责将之前 details.cshtml 的内容进行渲染:
@viewbag.title图书商城
分类
@renderbody()
_viewstart.cshtml 该文件表示默认的布局页为该视图文件:
@{ layout = ~/views/shared/_layout.cshtml; }
3.网站的根目录下也要添加一个名为 contents 的文件夹,用于存放 css。
site.css
现在,分页也已经有了效果,基本界面就出来了。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product