学习ASP.NET MVC5的一个轻量级的NinJect框架学习的第二天
{ /// <summary>
/// 书模型集合
/// </summary>
/*我们通过该接口就可以得到对应类的相关信息,
而不需要去管该数据如何存储,以及存储的位置,这就是存储库模式的本质。*/
IQueryable<Book> Books { get; }
}
新建一个Concrete文件夹新建一个EfDbContext类,他派生与Dbcontext,他会为数据库中的每一个表定义一个属性(这里是Books)
DbSet<Book>为Book的实体模型
/// <summary>
/// 书的上下文对象
/// </summary>
public class EfDbContext: DbContext
{
public DbSet<Book> Books { get; set; }
}
再创建EfBookRepository存储类库,它实现 IBookRepository 接口,使用了上文创建的 EfDbContext 上下文对象,包含了具体的方法定义
public class EfIBookRepository :IbookRepository
{
private readonly EfDbContext _context = new EfDbContext();
public IQueryable<Book> Books => _context.Books;
}
再接下来创建一个Entities文件夹
//为Book添加一个特性
[Table("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; }
}
再回到WebUI
新建一个文件夹存放我们自定义的工厂 新建一个NinjectControllerFactory 的类 他继承了DefaultControllerFactory这个控制器工厂的类
在这里面也可以添加自定义的代码,可以改变MVC的默认行为
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>
/// 添加绑定
/// 因为我们使用了 Ninject 容器,并且需要对控制器中的构造函数中的参数 IBookRepository 进行解析,
/// 告诉他将使用哪个对象对该接口进行服务,也就是需要修改之前的 AddBindings 方法
/// </summary>
private void AddBindings()
{
//这里注意 每添加一个接口这里就要进行绑定 上面是解释
_kernel.Bind<IbookRepository>().To<EfIBookRepository>();
// _kernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>();
}
在这里还要在Global.asax里添加一段代码,告诉 MVC 用新建的类来创建控制器对象
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
///ControllerBuilder这个类动态的生成一个控制器,设置指定的控制器工厂
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
现在要为项目添加控制器,视图了
public class BookController : Controller
{
private readonly IbookRepository _bookRepository;
public int PageSize = 5;
public BookController(IbookRepository bookRepository)
{
_bookRepository = bookRepository;
}
/// <summary>
/// 首页显示全部书的信息,并分页
/// </summary>
/// <param name="category"></param>
/// <param name="pageIndex"></param>
/// <returns></returns>
public ActionResult Details(string category, int pageIndex = 1)
{
var model = new BookDetailsViewModels
{
Books =
_bookRepository.Books.Where(x => category == null || x.Category == category)
.OrderBy(x => x.Id)
.Skip((pageIndex - 1) * PageSize)
.Take(PageSize),
CurrentCategory = category,
PageSize = PageSize,
PageIndex = pageIndex,
TotalItems = _bookRepository.Books.Count(x => category == null || x.Category == category)
};
return View(model);
}
}
@model Wen.BooksStore.WebUI.Models.BookDetailsViewModels
@{
ViewBag.Title = "Books";
}
<!DOCTYPE html>
@foreach (var item in Model.Books)
{
Html.RenderPartial("_BookSummary", item);
}
<div class="pager">
@Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
</div>
现在基本可以显示了 接下来就是配置伟大的路由了
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Book", action = "Details" }
);
routes.MapRoute(
name: null,
url: "{controller}/{action}/{category}",
defaults: new { controller = "Book", action = "Details" }
);
routes.MapRoute(
name: null,
url: "{controller}/{action}/{category}/{pageIndex}",
defaults: new { controller = "Book", action = "Details", pageIndex = UrlParameter.Optional }
);
}
现在可以显示了 那我就接下来做一个购物车实现购买吧
在Abstract文件夹先添加IOrderProcessor接口
public interface IOrderProcessor
{/// <summary>
/// 处理订单
/// </summary>
/// <param name="cart"></param>
/// <param name="contact"></param>
void ProcessOrder(Cart cart,Contact contact);
}
并在Concrete文件夹下添加EmailOrderProcessor类并继承IOrderProcessor
/// <summary>
/// 处理订单
/// </summary>
/// <param name="cart"></param>
/// <param name="contact"></param>
public void ProcessOrder(Cart cart, Contact contact)
{
if (string.IsNullOrEmpty(contact.Email))
{
throw new Exception("Email 不能为空!");
}
var sb = new StringBuilder();
foreach (var item in cart.GetCarItems)
{
sb.AppendLine($"《{item.Book.Name}》:{item.Book.Price} * {item.Quantity} = {item.Book.Price * item.Quantity}");
}
sb.AppendLine($"总额:{cart.GetCarItems.Sum(x => x.Quantity * x.Book.Price)}");
sb.AppendLine();
sb.AppendLine($"联系人:{contact.Name} {contact.Address}");
//设置发件人,发件人需要与设置的邮件发送服务器的邮箱一致
var fromAddr = new MailAddress(Sender.Account);
var message = new MailMessage { From = fromAddr };
//设置收件人,可添加多个,添加方法与下面的一样
message.To.Add(contact.Email);
//设置抄送人
message.CC.Add(Sender.Account);
//设置邮件标题
message.Subject = "您的订单正在出库...";
//设置邮件内容
message.Body = sb.ToString();
//设置邮件发送服务器,服务器根据你使用的邮箱而不同,可以到相应的 邮箱管理后台查看,下面是QQ的
var client = new SmtpClient("smtp.qq.com", 25)
{
Credentials = new NetworkCredential(Sender.Account, Sender.Password),
EnableSsl = true
};
//设置发送人的邮箱账号和密码
//启用ssl,也就是安全发送
//发送邮件
client.Send(message);
}
接下来在Entitites文件夹下添加Cart购物车实体模型
public class Cart
{
private readonly List<CartItem> _cartitems = new List<CartItem>();
public IList<CartItem> GetCarItems => _cartitems;
/// <summary>
/// 添加书的模型
/// </summary>
/// <param name="book"></param>
/// <param name="quantity"></param>
public void AddBook(Book book,int quantity)
{
if (_cartitems.Count==0)
{
_cartitems.Add(new CartItem() { Book = book, Quantity = quantity });
return;
}
var model = _cartitems.FirstOrDefault(x=>x.Book.Id==book.Id);
if (model==null)
{
_cartitems.Add(new CartItem() {Book=book,Quantity=quantity });
return;
}
model.Quantity += quantity;
}
/// <summary>
/// 移除书的模型
/// </summary>
/// <param name="book"></param>
public void RemoveBook(Book book)
{
var model = _cartitems.FirstOrDefault(x=>x.Book.Id==book.Id);
if (model==null)
{
return;
}
_cartitems.RemoveAll(x=>x.Book.Id==book.Id);
}
/// <summary>
/// 清空购物车
/// </summary>
public void Clear()
{
_cartitems.Clear();
}
/// <summary>
/// 统计总额
/// </summary>
/// <returns></returns>
public decimal ComputeTotalValue()
{
return _cartitems.Sum(x => x.Book.Price * x.Quantity);
}
}
再添加一个购物车项存放添加的书并显示用户添加的
public class CartItem
{
/// <summary>
/// 书-+--
/// </summary>
public Book Book { get; set; }
/// <summary>
/// 数量
/// </summary>
public int Quantity { get; set; }
}
一切都完
现在做添加到购物车吧
public class CartController : Controller
{
private readonly IbookRepository _bookRepository;
private readonly IOrderProcessor _orderprocessor;
public CartController(IbookRepository bookRepository,IOrderProcessor orderprocessor)
{
_bookRepository = bookRepository;
_orderprocessor = orderprocessor;
}
/// <summary>
/// 首页
/// </summary>
/// <returns></returns>
public ViewResult Index(string returnUrl)
{
return View(new CartViewModels() {
Cart = GetCart(),
ReturnUrl=returnUrl
});
}
/// <summary>
/// 添加到购物车
/// </summary>
/// <param name="id"></param>
/// <param name="returnUrl"></param>
/// <returns></returns>
public RedirectToRouteResult AddToCart(int id, string returnUrl)
{
var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id);
if (book != null)
{
GetCart().AddBook(book, 1);
}
return RedirectToAction("Index", new { returnUrl });
}
/// <summary>
/// 移除书的模型
/// </summary>
/// <param name="id"></param>
/// <param name="returnUrl"></param>
/// <returns></returns>
public RedirectToRouteResult RemoveFromCart(int id,string returnUrl)
{
var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id);
if (book != null)
{
GetCart().RemoveBook(book);
}
return RedirectToAction("Index", new {returnUrl });
}
/// <summary>
/// 获取购物车
/// </summary>
/// <returns></returns>
private Cart GetCart()
{
var cart = (Cart)Session["Cart"];
if (cart != null) return cart;
cart = new Cart();
Session["Cart"] = cart;
return cart;
}
/// <summary>
/// 摘要
/// </summary>
/// <returns></returns>
public PartialViewResult Summary()
{
return PartialView(GetCart());
}
/// <summary>
/// 结算
/// </summary>
/// <returns></returns>
public ViewResult Checkout()
{
return View(new Contact());
}
/// <summary>
/// 结算
/// </summary>
/// <param name="contact"></param>
/// <returns></returns>
[HttpPost]
public ViewResult Checkout(Contact contact)
{
if (!ModelState.IsValid)
return View(contact);
var cart = GetCart();
_orderprocessor.ProcessOrder(cart, contact);
cart.Clear();
return View("Thanks");
}
/// <summary>
/// 清空购物车
/// </summary>
/// <param name="id"></param>
/// <param name="returnUrl"></param>
/// <returns></returns>
public RedirectToRouteResult Clear(string returnUrl)
{
GetCart().Clear();
return RedirectToAction("Index",new {returnUrl });
}
}
这里注意的是只添加一个视图就是Index
其他三个页面都添加
再新建一个视图文件夹Shared
_Layout页面
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<link href="~/Contents/Site.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
<div id="header">
@{ Html.RenderAction("Summary", "Cart");}
<div class="title">图书商城</div>
</div>
<div id="sideBar">
@{ Html.RenderAction("Sidebar", "Nav"); }
</div>
<div>
@RenderBody()
</div>
</body>
</html>
_BookSummary页面
@model Wen.BooksStore.Domain.Entitites.Book
<div class="item">
<h3>@Model.Name</h3>
@Model.Description
<h4>@Model.Price.ToString("C")</h4>
@using (Html.BeginForm("AddToCart", "Cart"))
{
var id = Model.Id;
@Html.HiddenFor(x => id);
@Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<input type="submit" value="+ 添加到购物车" />
}
<br />
<hr />
</div>
最后在Views文件夹下添加_ViewStart页面
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
补充一个 书的分类 创建Nav控制器
public class NavController : Controller
{
private readonly IbookRepository _bookRepository;
public NavController(IbookRepository bookRepository)
{
_bookRepository = bookRepository;
}
// GET: Nav
public PartialViewResult Sidebar(string category= null)
{
ViewBag.CurrentCategory = category;
var categories = _bookRepository.Books.Select(x=>x.Category).Distinct().OrderBy(x=>x);
return PartialView(categories);
}
@model IEnumerable<string>
<ul>
<li>@Html.ActionLink("所有分类","Details","Book")</li>
@foreach (var item in Model)
{
<li>@Html.RouteLink(item, new { controller = "Book", action = "Details", category = item, pageIndex = 1 }, new { @class = item == ViewBag.CurrentCategory ? "selected" : null })</li>
}
</ul>
}
最后还有一个重大事,就是整个的样式 在WebUI下新建一个文件夹 Contents 新建一个样式Site
body {
}
#header, #content, #sideBar {
display: block;
}
#header {
background-color: green;
border-bottom: 2px solid #111;
color: White;
}
#header, .title {
font-size: 1.5em;
padding: .5em;
}
#sideBar {
float: left;
width: 8em;
padding: .3em;
}
#content {
border-left: 2px solid gray;
margin-left: 10em;
padding: 1em;
}
.pager {
text-align: right;
padding: .5em 0 0 0;
margin-top: 1em;
}
.pager A {
font-size: 1.1em;
color: #666;
padding: 0 .4em 0 .4em;
}
.pager A:hover {
background-color: Silver;
}
.pager A.selected {
background-color: #353535;
color: White;
}
.item input {
float: right;
color: White;
background-color: green;
}
.table {
width: 100%;
padding: 0;
margin: 0;
}
.table th {
font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
color: #4f6b72;
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
border-top: 1px solid #C1DAD7;
letter-spacing: 2px;
text-transform: uppercase;
text-align: left;
padding: 6px 6px 6px 12px;
background: #CAE8EA no-repeat;
}
.table td {
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
background: #fff;
font-size: 14px;
padding: 6px 6px 6px 12px;
color: #4f6b72;
}
.table td.alt {
background: #F5FAFA;
color: #797268;
}
.table th.spec, td.spec {
border-left: 1px solid #C1DAD7;
}
.bookSummary {
width: 15%;
float: right;
margin-top: 1.5%;
}
.error {
color: red;
}
最后大搞成了
最后总结一下,Ninject是一个IOC容器用来解决程序中组件的耦合问题,它的目的在于做到最少配置。
其他的的IOC工具过于依赖配置文件,需要使用assembly-qualified名称来进行定义,庸长且复杂常常因为打错字而破坏程序,虽然不是很懂,
但是我会一直继续摸索下去
学习ASP.NET MVC5的一个轻量级的NinJect框架学习的第二天的更多相关文章
- ASP.NET MVC5的一个轻量级的框架学习的第一天
第二步第三部 这是第一天的小试成功,怪自己太笨了,一个错排查好久,还好有源码看着了解,后续还得多努力,
- ASP.NET MVC5 网站开发实践(一) - 项目框架
前几天算是开题了,关于怎么做自己想了很多,但毕竟没做过项目既不知道这些想法有无必要,也不知道能不能实现,不过邓爷爷说过"摸着石头过河"吧.这段时间看了一些博主的文章收获很大,特别是 ...
- ASP.NET MVC5 网站开发实践(一) - 项目框架(转)
前几天算是开题了,关于怎么做自己想了很多,但毕竟没做过项目既不知道这些想法有无必要,也不知道能不能实现,不过邓爷爷说过“摸着石头过河”吧.这段时间看了一些博主的文章收获很大,特别是@kencery,依 ...
- NET Core写了一个轻量级的Interception框架[开源]
NET Core写了一个轻量级的Interception框架[开源] ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只 ...
- 如何在Java生态圈选择一个轻量级的RESTful框架?
在微服务流行的今天,我们会从纵向和横向分解代码的逻辑,将一些独立的无状态的代码单元实现为微服务,可以将它们发布到一些分布式计算单元或者Docker中,并在性能需要的时候及时地创建更多的服务单元.微服务 ...
- 学习asp.net mvc5心得
前几天时间大体学习了一下asp.net mvc5的应用,感觉最主要的就是要区分这以模式设计,其他的都是在asp.net下的基础操作 1参数的传递注意 2路由的设置规则 3model的应用
- 一个轻量级分布式RPC框架--NettyRpc
1.背景 最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章<轻量级分布式 RPC 框架>,作者用Zookeeper.Netty和Spring写了一个轻量级的分布式RPC ...
- 为了支持AOP的编程模式,我为.NET Core写了一个轻量级的Interception框架[开源]
ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只是一个很轻量级的框架,但是在大部分情况下能够满足我们的需要.不过我觉得 ...
- 一个轻量级分布式 RPC 框架 — NettyRpc
原文出处: 阿凡卢 1.背景 最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章<轻量级分布式 RPC 框架>,作者用Zookeeper.Netty和Spring写了一个 ...
随机推荐
- update外联表,用另一个表数据更新本表数据
update s set s.classbid = lc.itemidfrom dbo.Lv_servers as s INNER JOIN dbo.Lv_LineChannel as lc O ...
- Java类加载器(ClassLoader)
类加载的机制的层次结构 每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Jav ...
- ES6 一些新特性的总结
一.箭头函数 ES6中新增了一个箭头函数 ()=>,箭头函数通俗点讲就是匿名函数.箭头函数还有不同点在于改变函数中this,和js中的.bind 的方法差不多,继承后指向的不是最新的函数, ...
- ie的兼容方法,条件注释的方法
1.终极方法:条件注释 <!--[if lte IE 6]> 这段文字仅显示在 IE6及IE6以下版本. <![endif]--> <!--[if gte IE 6]&g ...
- vue 做登陆页面 ( 登陆成功后去掉注册和登陆按钮 显示用户名)
1.当登陆成功 显示用户名且去掉登陆和注册按钮 2.data里声明 后 就在登陆的方法里调用啦 下面说一下登陆的方法. 1.登陆的按钮代码在第一张图片里 2.登陆的弹出框 3.方法 ps:另一种 ...
- 一步一步学Silverlight 2系列(7):全屏模式支持
一步一步学Silverlight 2系列(7):全屏模式支持 概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言V ...
- set STL 简单说说
set 这个容器,可以排序,以及去掉重复的东西 #include<bits/stdc++.h> using namespace std; int main() { string s; se ...
- 关于python代码的性能
在python中性能测试是一个很难应付的任务,因为它在反复地优化,也许版本和版本之间差别很大.python中的一个主要的原则是,首先为了简单和可读性去编写代码,在程序运行后,并证明了确实有必要考虑性能 ...
- Android隐藏Activity和图标
今天发现4.0以后如果不写Activity只写BroadcastReceiver的话,这个广播接收器是不能运行的.经过查询,好像是HoneyComb之后添加了安全机制,规定必须运行一次Activity ...
- 压缩&&解压
压缩与解压缩: ############################################################# tar xvf wordpress.tar ## ...