新建一个Abstract文件夹   放置一些抽象的类,如接口
  我们通过该接口就可以得到对应类的相关信息, 不需要去管该数据如何存储,以及存储的位置,这就是存储库模式的本质
 public  interface IbookRepository
    {    /// <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框架学习的第二天的更多相关文章

  1. ASP.NET MVC5的一个轻量级的框架学习的第一天

    第二步第三部 这是第一天的小试成功,怪自己太笨了,一个错排查好久,还好有源码看着了解,后续还得多努力,

  2. ASP.NET MVC5 网站开发实践(一) - 项目框架

    前几天算是开题了,关于怎么做自己想了很多,但毕竟没做过项目既不知道这些想法有无必要,也不知道能不能实现,不过邓爷爷说过"摸着石头过河"吧.这段时间看了一些博主的文章收获很大,特别是 ...

  3. ASP.NET MVC5 网站开发实践(一) - 项目框架(转)

    前几天算是开题了,关于怎么做自己想了很多,但毕竟没做过项目既不知道这些想法有无必要,也不知道能不能实现,不过邓爷爷说过“摸着石头过河”吧.这段时间看了一些博主的文章收获很大,特别是@kencery,依 ...

  4. NET Core写了一个轻量级的Interception框架[开源]

    NET Core写了一个轻量级的Interception框架[开源] ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只 ...

  5. 如何在Java生态圈选择一个轻量级的RESTful框架?

    在微服务流行的今天,我们会从纵向和横向分解代码的逻辑,将一些独立的无状态的代码单元实现为微服务,可以将它们发布到一些分布式计算单元或者Docker中,并在性能需要的时候及时地创建更多的服务单元.微服务 ...

  6. 学习asp.net mvc5心得

    前几天时间大体学习了一下asp.net mvc5的应用,感觉最主要的就是要区分这以模式设计,其他的都是在asp.net下的基础操作 1参数的传递注意 2路由的设置规则 3model的应用

  7. 一个轻量级分布式RPC框架--NettyRpc

    1.背景 最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章<轻量级分布式 RPC 框架>,作者用Zookeeper.Netty和Spring写了一个轻量级的分布式RPC ...

  8. 为了支持AOP的编程模式,我为.NET Core写了一个轻量级的Interception框架[开源]

    ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只是一个很轻量级的框架,但是在大部分情况下能够满足我们的需要.不过我觉得 ...

  9. 一个轻量级分布式 RPC 框架 — NettyRpc

    原文出处: 阿凡卢 1.背景 最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章<轻量级分布式 RPC 框架>,作者用Zookeeper.Netty和Spring写了一个 ...

随机推荐

  1. update外联表,用另一个表数据更新本表数据

    update s set s.classbid = lc.itemidfrom    dbo.Lv_servers as s INNER JOIN dbo.Lv_LineChannel as lc O ...

  2. Java类加载器(ClassLoader)

    类加载的机制的层次结构 每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Jav ...

  3. ES6 一些新特性的总结

    一.箭头函数 ES6中新增了一个箭头函数   ()=>,箭头函数通俗点讲就是匿名函数.箭头函数还有不同点在于改变函数中this,和js中的.bind  的方法差不多,继承后指向的不是最新的函数, ...

  4. ie的兼容方法,条件注释的方法

    1.终极方法:条件注释 <!--[if lte IE 6]> 这段文字仅显示在 IE6及IE6以下版本. <![endif]--> <!--[if gte IE 6]&g ...

  5. vue 做登陆页面 ( 登陆成功后去掉注册和登陆按钮 显示用户名)

    1.当登陆成功  显示用户名且去掉登陆和注册按钮 2.data里声明  后  就在登陆的方法里调用啦 下面说一下登陆的方法. 1.登陆的按钮代码在第一张图片里 2.登陆的弹出框 3.方法 ps:另一种 ...

  6. 一步一步学Silverlight 2系列(7):全屏模式支持

    一步一步学Silverlight 2系列(7):全屏模式支持   概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言V ...

  7. set STL 简单说说

    set 这个容器,可以排序,以及去掉重复的东西 #include<bits/stdc++.h> using namespace std; int main() { string s; se ...

  8. 关于python代码的性能

    在python中性能测试是一个很难应付的任务,因为它在反复地优化,也许版本和版本之间差别很大.python中的一个主要的原则是,首先为了简单和可读性去编写代码,在程序运行后,并证明了确实有必要考虑性能 ...

  9. Android隐藏Activity和图标

    今天发现4.0以后如果不写Activity只写BroadcastReceiver的话,这个广播接收器是不能运行的.经过查询,好像是HoneyComb之后添加了安全机制,规定必须运行一次Activity ...

  10. 压缩&&解压

    压缩与解压缩: ############################################################# tar xvf wordpress.tar       ## ...