gpt4 book ai didi

一步步打造简单的MVC电商网站BooksStore(4)

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 32 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章一步步打造简单的MVC电商网站BooksStore(4)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

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

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

      《一步步打造一个简单的 MVC 电商网站 - BooksStore(二)》 。

  《一步步打造一个简单的 MVC 电商网站 - BooksStore(三)》 。

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

简介 。

  上一节我们完成了两个主要功能:完成了整个购物车的流程,以及订单处理(发邮件进行通知),今天我们来学习一下最基本的增删改查,以及登录认证过滤器,加入防 CSRF 攻击,本系列已完结.

  该系列主要功能与知识点如下:

    分类、产品浏览、购物车、结算、CRUD(增删改查) 管理、发邮件、分页、模型绑定、认证过滤器和单元测试等.

     【备注】项目使用 VS2015 + C#6 进行开发,有问题请发表在留言区哦,还有,页面长得比较丑,请见谅.

  。

目录 。

  • 基本的增删改查 CRUD
  • 登录授权认证过滤

  。

基本的增删改查 CRUD 。

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

一步步打造简单的MVC电商网站BooksStore(4)

 
    
/// <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:

一步步打造简单的MVC电商网站BooksStore(4)

 
<!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>
 

  。

  。

一步步打造简单的MVC电商网站BooksStore(4)

  。

   编辑,我把新增和编辑的位置放在一块,使用 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");        }
 

  。

  更新存储库中的方法:

一步步打造简单的MVC电商网站BooksStore(4)

  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>
 

一步步打造简单的MVC电商网站BooksStore(4)

图:错误提示 。

一步步打造简单的MVC电商网站BooksStore(4)

  。

  删除 。

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

  。

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

一步步打造简单的MVC电商网站BooksStore(4)

  。

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

  。

一步步打造简单的MVC电商网站BooksStore(4)

  执行效果:

一步步打造简单的MVC电商网站BooksStore(4)

  。

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

  。

登录授权认证过滤 。

  上面是一个 Admin 的后台管理操作,不是每一个用户都能够进入管理的,所以现在加入登录授权认证功能,只有成功后,才能进入管理界面.

  先在配置文件 WebConfig.cs 中加入 。

 
<authentication mode="Forms">      <forms loginUrl="~/Account/Login" timeout="2880">        <credentials passwordFormat="Clear">          <user name="admin" password="123"/>        </credentials>      </forms></authentication>
 

  。

<?xml version="1.0" encoding="utf-8"?><!--  For more information on how to configure your ASP.NET application, please visit  http://go.microsoft.com/fwlink/?LinkId=301880  --><configuration>  <connectionStrings>    <add name="EfDbContext" connectionString="server=.;database=TestDb;uid=sa;pwd=123" providerName="System.Data.SqlClient"/>  </connectionStrings>  <appSettings>    <add key="webpages:Version" value="3.0.0.0"/>    <add key="webpages:Enabled" value="false"/>    <add key="ClientValidationEnabled" value="true"/>    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>    <add key="SendEmailName" value="943239005@qq.com"/>  </appSettings>  <system.web>    <authentication mode="Forms">      <forms loginUrl="~/Account/Login" timeout="2880">        <credentials passwordFormat="Clear">          <user name="admin" password="123"/>        </credentials>      </forms>    </authentication>    <compilation debug="true" targetFramework="4.6.1"/>    <httpRuntime targetFramework="4.6.1"/>    <httpModules>      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/>    </httpModules>  </system.web>  <runtime>    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">      <dependentAssembly>        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>      </dependentAssembly>      <dependentAssembly>        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>      </dependentAssembly>      <dependentAssembly>        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>        <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>      </dependentAssembly>    </assemblyBinding>  </runtime>  <system.codedom>    <compilers>      <compiler language="c#;cs;csharp" extension=".cs"        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>    </compilers>  </system.codedom>  <system.webServer>    <validation validateIntegratedModeConfiguration="false"/>    <modules>      <remove name="ApplicationInsightsWebTracking"/>      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"        preCondition="managedHandler"/>    </modules>  </system.webServer></configuration>

WebConfig.cs 。

  

  在这里使用的授权认证模式为表单认证,为了简化与数据库的交互操作,采取的是硬编码的形式。如果尚未得到认证,会跳转到 Account/Login 的地址让管理员先进行登录,timeout 表示登录(即认证)成功的保持时长为 2880 分钟(即 48 小时),而 name 表示的就是用户名, password 表示的就是登录密码。   。

  。

  这里采用的是授权认证过滤器,我们需要对要认证后才能进入的控制器添加一个特性[Authorize],即对 AdminController 添加该特性.

一步步打造简单的MVC电商网站BooksStore(4)

  。

  。

  新建表单认证提供器,一个接口和一个实现:

一步步打造简单的MVC电商网站BooksStore(4)

  IAuthProvider.cs:

 
    
public interface IAuthProvider    {        /// <summary>        /// 认证        /// </summary>        /// <param name="userName"></param>        /// <param name="password"></param>        /// <returns></returns>        bool Auth(string userName, string password);    }
 

  。

  FormsAuthProvider.cs:

 
    
/// <summary>    /// 表单认证提供者    /// </summary>    public class FormsAuthProvider:IAuthProvider    {        /// <summary>        /// 认证        /// </summary>        /// <param name="userName"></param>        /// <param name="password"></param>        /// <returns></returns>        public bool Auth(string userName, string password)        {            var result = FormsAuthentication.Authenticate(userName, password);            if (result)            {                //设置认证 Cookie                FormsAuthentication.SetAuthCookie(userName, false);            }            return result;        }    }
 

  

  AddBindings() 方法中注册:

 
        
/// <summary>        /// 添加绑定        /// </summary>        private void AddBindings()        {            _kernel.Bind<IBookRepository>().To<EfBookRepository>();            _kernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>();            _kernel.Bind<IAuthProvider>().To<FormsAuthProvider>();        }
 

  。

一步步打造简单的MVC电商网站BooksStore(4)

 
    
/// <summary>    /// 登录视图模型    /// </summary>    public class LoginViewModel    {        [Required(ErrorMessage = "用户名不能为空")]        public string UserName { get; set; }        [Required(ErrorMessage = "密码不能为空")]        [DataType(DataType.Password)]        public string Password { get; set; }    }
 

  。

  新建 AccountController 。

一步步打造简单的MVC电商网站BooksStore(4)

  。

 
    
public class AccountController : Controller    {        private readonly IAuthProvider _authProvider;        public AccountController(IAuthProvider authProvider)        {            _authProvider = authProvider;        }        /// <summary>        /// 登录        /// </summary>        /// <returns></returns>        public ActionResult Login()        {            return View();        }        /// <summary>        /// 登录        /// </summary>        /// <param name="model"></param>        /// <returns></returns>        [HttpPost]        [ValidateAntiForgeryToken]        public ActionResult Login(LoginViewModel model)        {            if (!ModelState.IsValid)            {                return View(new LoginViewModel());            }            var result = _authProvider.Auth(model.UserName, model.Password);            if (result) return RedirectToAction("Index", "Admin");            ModelState.AddModelError("", "账号或用户名有误");            return View(new LoginViewModel());        }    }
 

  。

  Login.cshtml 登录页面:

@model Wen.BooksStore.WebUI.Models.LoginViewModel@{    Layout = null;}<!DOCTYPE html><html lang="zh"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>登录</title>    @*<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">*@    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">    @*<link href="~/Contents/Login/css/htmleaf-demo.css" rel="stylesheet" />*@    <style type="text/css">        @@import url(https://fonts.googleapis.com/css?family=Roboto:300);        .login-page {            margin: auto;            padding: 8% 0 0;            width: 360px;        }        .form {            background: #FFFFFF;            box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);            margin: 0 auto 100px;            max-width: 360px;            padding: 45px;            position: relative;            text-align: center;            z-index: 1;        }        .form input {            background: #f2f2f2;            border: 0;            box-sizing: border-box;            font-family: "Roboto", sans-serif;            font-size: 14px;            margin: 0 0 15px;            outline: 0;            padding: 15px;            width: 100%;        }        .form button {            -webkit-transition: all 0.3 ease;            background: #4CAF50;            border: 0;            color: #FFFFFF;            cursor: pointer;            font-family: "Microsoft YaHei", "Roboto", sans-serif;            font-size: 14px;            outline: 0;            padding: 15px;            text-transform: uppercase;            transition: all 0.3 ease;            width: 100%;        }        .form button:hover, .form button:active, .form button:focus { background: #43A047; }        .form .message {            color: #b3b3b3;            font-size: 12px;            margin: 15px 0 0;        }        .form .message a {            color: #4CAF50;            text-decoration: none;        }        .form .register-form { display: none; }        .container {            margin: 0 auto;            max-width: 300px;            position: relative;            z-index: 1;        }        .container:before, .container:after {            clear: both;            content: "";            display: block;        }        .container .info {            margin: 50px auto;            text-align: center;        }        .container .info h1 {            color: #1a1a1a;            font-size: 36px;            font-weight: 300;            margin: 0 0 15px;            padding: 0;        }        .container .info span {            color: #4d4d4d;            font-size: 12px;        }        .container .info span a {            color: #000000;            text-decoration: none;        }        .container .info span .fa { color: #EF3B3A; }        body {            -moz-osx-font-smoothing: grayscale;            -webkit-font-smoothing: antialiased;            background: #76b852; /* fallback for old browsers */            background: -webkit-linear-gradient(right, #76b852, #8DC26F);            background: -moz-linear-gradient(right, #76b852, #8DC26F);            background: -o-linear-gradient(right, #76b852, #8DC26F);            background: linear-gradient(to left, #76b852, #8DC26F);            font-family: "Roboto", sans-serif;        }    </style>    <!--[if IE]>        <script src="http://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>    <![endif]-->    <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="wrapper" class="login-page">        <div id="login_form" class="form">            @using (Html.BeginForm("Login", "Account", FormMethod.Post, new { @class = "login-form" }))            {                <span style="float: left; color: red;">@Html.ValidationSummary()</span>                @Html.AntiForgeryToken()                @Html.TextBoxFor(x => x.UserName, new { placeholder = "用户名" })                @Html.EditorFor(x => x.Password, new { placeholder = "密码",  })                <input type="submit" value="登 录" />            }        </div>    </div></body></html>

Login.cshtml 。

一步步打造简单的MVC电商网站BooksStore(4)

  。

一步步打造简单的MVC电商网站BooksStore(4)

  。

  【备注】ValidateAntiForgeryToken 特性用于防止跨站请求伪造(CSRF)攻击.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我。 原文链接:http://www.cnblogs.com/liqingwen/p/6658975.html 。

最后此篇关于一步步打造简单的MVC电商网站BooksStore(4)的文章就讲到这里了,如果你想了解更多关于一步步打造简单的MVC电商网站BooksStore(4)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com