[.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(四)

一步步打造一个简单的 MVC 电商网站 - BooksStore(四)

  本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore

  《一步步打造一个简单的 MVC 电商网站 - BooksStore(一)》(发布时间:2017-03-30 )

一步步打造一个简单的 MVC 电商网站 - BooksStore(二)》(发布时间:2017-03-31)

  《一步步打造一个简单的 MVC 电商网站 - BooksStore(三)》(发布时间:2017-04-01)

基本的增删改查 CRUD

  我们创建一个新的控制器进行增删改查功能,AdminController,并添加一个显示所有数据的方法:

    /// <summary>
    /// 后台管理控制器
    /// </summary>
    public class AdminController : Controller
    {
        private readonly IBookRepository _bookRepository;

        public AdminController(IBookRepository bookRepository)
        {
            _bookRepository = bookRepository;
        }

        /// <summary>
        /// 首页
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View(_bookRepository.Books);
        }
    }

  不在沿用之前的布局页了,创建一个新的布局页 _AdmindLayout.cshtml:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/Contents/admin/Site.css" rel="stylesheet" />
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

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

Site.css

  对应的 Index.cshtml:

@model IEnumerable<Wen.BooksStore.Domain.Entities.Book>

@{
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<p>
    @Html.ActionLink("新增", "Edit")
</p>
<table class="table">
    <tr>
        <th>
            名称
        </th>
        <th>
            描述
        </th>
        <th>
            价格
        </th>
        <th>
            分类
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Description)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Category)
            </td>
            <td>
                @Html.ActionLink("编辑", "Edit", new { id = item.Id })
                @using (Html.BeginForm("Delete", "Admin", FormMethod.Post, new { style = "display:inline;" }))
                {
                    @Html.Hidden("id", item.Id)
                    <input type="submit" value="删除" />
                }
            </td>
        </tr>
    }

</table>

   编辑,我把新增和编辑的位置放在一块,使用 id 进行区分,如果 id = 0 就表示新增的信息。

  在 AdminCtroller 中添加关于编辑的方法

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult Edit(int id = 0)
        {
            if (id == 0)
            {
                return View(new Book());
            }

            var model = _bookRepository.Books.FirstOrDefault(x => x.Id == id);
            return View(model);
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="book"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Edit(Book book)
        {
            if (!ModelState.IsValid)
            {
                return View(book);
            }

            _bookRepository.SaveBook(book);
            return RedirectToAction("Index");
        }

  更新存储库中的方法:

  IBookRepository.cs

    /// <summary>
    /// 书存储库接口
    /// </summary>
    public interface IBookRepository
    {
        /// <summary>
        /// 书模型集合
        /// </summary>
        IQueryable<Book> Books { get; }

        /// <summary>
        /// 保存书
        /// </summary>
        /// <param name="book"></param>
        /// <returns></returns>
        int SaveBook(Book book);

        /// <summary>
        /// 删除书
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Book DeleteBook(int id);
    }

  EfBookRepository.cs

    /// <summary>
    /// 书存储库
    /// </summary>
    public class EfBookRepository : IBookRepository
    {
        private readonly EfDbContext _context = new EfDbContext();

        /// <summary>
        /// 书模型集合
        /// </summary>
        public IQueryable<Book> Books => _context.Books;

        /// <summary>
        /// 保存书
        /// </summary>
        /// <param name="book"></param>
        /// <returns></returns>
        public int SaveBook(Book book)
        {
            if (book.Id == 0)
            {
                _context.Books.Add(book);
            }
            else
            {
                var model = _context.Books.Find(book.Id);

                if (model==null)
                {
                    return 0;
                }

                model.Category = book.Category;
                model.Description = book.Description;
                model.Name = book.Name;
                model.Price = book.Price;
            }

            return _context.SaveChanges();
        }

        /// <summary>
        /// 删除书
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Book DeleteBook(int id)
        {
            var model = _context.Books.Find(id);

            if (model == null)
            {
                return null;
            }

            _context.Books.Remove(model);
            _context.SaveChanges();

            return model;
        }
    }

  需要对 Book 模型加上验证用的特性:

    [Table("Book")]
    public class Book
    {
        /// <summary>
        /// 标识
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        [Required(ErrorMessage = "名称不能为空")]
        public string Name { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        [Required(ErrorMessage = "描述不能为空")]
        public string Description { get; set; }

        /// <summary>
        /// 价格
        /// </summary>
        [Required(ErrorMessage = "价格不能为空")]
        [Range(0.01, double.MaxValue, ErrorMessage = "请填写合适的价格")]
        public decimal Price { get; set; }

        /// <summary>
        /// 分类
        /// </summary>
        [Required(ErrorMessage = "分类不能为空")]
        public string Category { get; set; }
    }

  _AdminLayout.cshtml 需要引入验证用的 js(客户端验证):

    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

  Edit.cshtml

@model Wen.BooksStore.Domain.Entities.Book

@{
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<h2>编辑</h2>

<div>
    @Html.ValidationSummary()

    <div>
        @using (Html.BeginForm())
        {
            @Html.HiddenFor(x => x.Id)
            <table>
                <tr>
                    <td>名称</td>
                    <td>@Html.TextBoxFor(x => x.Name)</td>
                </tr>
                <tr>
                    <td>价格</td>
                    <td>@Html.TextBoxFor(x => x.Price)</td>
                </tr>
                <tr>
                    <td>分类</td>
                    <td>@Html.TextBoxFor(x => x.Category)</td>
                </tr>
                <tr>
                    <td>描述</td>
                    <td>@Html.TextAreaFor(x => x.Description)</td>
                </tr>
            </table>
            <input type="submit" value="提交" />
        }
    </div>
</div>

图:错误提示

  删除

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Delete(int id)
        {
            _bookRepository.DeleteBook(id);
            return RedirectToAction("Index");
        }

  加入提示,我们在新增、编辑和删除时应该加入必要的提示信息,使用 TempData。

  /Admin/Index.cshtml 下的也要添加:

  执行效果:

  【备注】TempData 临时数据保存了一条信息,是一个“键/值”字典,类似会话 Session 和 ViewBag,它和 Session 的差别是,在 HTTP 请求结束后会被删除。因为这里使用了 RedirectToAction ,一条重定向指令,会告诉浏览器重定向请求到一个新地址,这时就不能使用 ViewBag,ViewBag 用于在控制器与视图之间传递数据,但它保持数据的时间不能比当前的 HTTP 请求长,重定向意味着用户是跨请求的,ViewBag 不能用于跨请求时传递数据。

时间: 2025-01-01 21:21:40

[.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(四)的相关文章

[.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(二)

一步步打造一个简单的 MVC 电商网站 - BooksStore(二) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore 前:<一步步打造一个简单的 MVC 电商网站 - BooksStore(一)> 简介 上一次我们尝试了:创建项目架构.创建域模型实体.创建单元测试.创建控制器与视图.创建分页和加入样式,而这一节我们会完成两个功能,分类导航与购物车. 主要功能与知识点如下: 分类.产品浏览.购物车.结算.CRUD(增删

[.NET] 一步步打造一个简单的 MVC 网站 - BooksStore

一步步打造一个简单的 MVC 网站 - BooksStore 简介 主要功能与知识点如下: 分类.产品浏览.购物车.结算.CRUD(增删改查) 管理.分页和单元测试. [备注]项目使用 VS2015 + C#6 进行开发. 一.创建项目架构 1.新建一个解决方案“BooksStore”,并添加以下项目: BooksStore.Domain:类库,存放域模型和逻辑,使用 EF: BooksStore.WebUI:Web 应用程序,存放视图和控制器,充当显示层: BoosStore.UnitTest

如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户

阅读目录 前言 怎么卖 领域服务的使用 回到现实 结语 一.前言 上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计.现在把剩余的“卖”这个动作给做了.这里提醒一下,正常情况下,我们的每一步业务设计都需要和领域专家进行沟通,尽可能的符合通用语言的表述.这里的领域专家包括但不限于当前开发团队中对这块业务最了解的开发人员.系统实际的使用人等. 二.怎么卖 如果在没有结合当前上下文的情况下,用通用语言来表述,我们很容易把代码写成下面的这个样子(其中DomainRegistry只是一个简单的工厂

[转]PHP实现MVC开发: 一个简单的MVC

今天研究了下PHP MVC结构,所以决定自己写个简单的MVC,以待以后有空再丰富.至于什么MVC结构,其实就是三个Model,Contraller,View单词的简称,,Model,主要任务就是把数据库或者其他文件系统的数据按 照我们需要的方式读取出来.View,主要负责页面的,把数据以html的形式显示给用户.Controller,主要负责业务逻辑,根据用户的 Request进行请求的分配,比如说显示登陆界面,就需要调用一个控制器userController的方法loginAction来显示.

PHP (20140523)PHP实现MVC开发: 一个简单的MVC

今天研究了下PHP MVC结构,所以决定自己写个简单的MVC,以待以后有空再丰富.至于什么MVC结构,其实就是三个Model,Contraller,View单词的简称,,Model,主要任务就是把数据库或者其他文件系统的数据按 照我们需要的方式读取出来.View,主要负责页面的,把数据以html的形式显示给用户.Controller,主要负责业务逻辑,根据用户的 Request进行请求的分配,比如说显示登陆界面,就需要调用一个控制器userController的方法loginAction来显示.

一个简单的MVC模型实现

function Event(sender) { this._sender = sender; this._listeners = []; } Event.prototype = { attach : function (listener) { this._listeners.push(listener); }, notify : function (args) { var index; for (index = 0; index < this._listeners.length; index

设计一个简单的mvc映射

在工作时,有一套框架,并不是很适合做后台,为此我在这个框架加了简单的mvc映射 首先为方便可以随时new自己想要的类,注册自己的__autoload方法,这里封装成一个类,当然类里面要封装好查找路径,注册的时候就是调用内部的loader成员方法: spl_autoload_register(array($this, 'loader')); 现在,我在Action文件夹(前面已经会自动加载这个文件夹相应的类文件),. 创建一个抽象类Action_Abstract,里面有抽象方法run,后期有act

【iOS开发-50】利用创建新的类实现代码封装,从而不知不觉实践一个简单的MVC实验

接上次案例谈代码封装.上次案例见:[iOS开发-48]九宫格布局案例:自动布局.字典转模型运用.id和instancetype区别.xib重复视图运用及与nib关系 代码封装的原则是:要保证视图控制器尽量少的接触到其他对象的属性,也就是说,尽量把数据或者属性封装到一个类里面,然后利用类或者对象的方法来调用或者设置数据.而是赤裸裸地把属性都写在视图控制器中.核心作用在于:减少视图控制器的代码量,把数据和属性的处理封装起来,这样也便于其他视图控制器的使用. 要做到的结果就是如下(我们要根据数组里面的

电商总结(八)如何打造一个小而精的电商网站架构

前面写过一些电商网站相关的文章,这几天有时间,就把之前写得网站架构相关的文章,总结整理一下.把以前的一些内容就连贯起来,这样也能系统的知道,一个最小的电商平台是怎么一步步搭建起来的.对以前的文章感兴趣的朋友可以看这个,http://www.cnblogs.com/zhangweizhong/category/879056.html 本文大纲: 1. 小型电商网站的架构 2. 日志与监控系统的解决方案 3. 构建数据库的主从架构 4. 基于共享存储的图片服务器架构 5. 移动M站建设 6. 系统容