Step by step create a simple MVC e-commerce website BooksStore (4), mvcbooksstore

Source: Internet
Author: User
Tags actionlink csrf attack connectionstrings

Step by step create a simple MVC e-commerce website BooksStore (4), mvcbooksstore

Build a simple MVC e-commerce website step by step-BooksStore (4)

GitHub address: https://github.com/liqingwen2015/Wen.BooksStore

Building a simple MVC e-commerce website step by step-BooksStore (I)

Building a simple MVC e-commerce website step by step-BooksStore (II)

Building a simple MVC e-commerce website step by step-BooksStore (III)

Building a simple MVC e-commerce website step by step-BooksStore (4)

Introduction

In the previous section, we completed two main functions: the entire shopping cart process and order processing (sending an email for notification). Today we will learn about the most basic addition, deletion, modification, and query functions, as well as the login authentication filter, add anti-CSRF attack, this series is complete.

The main functions and knowledge points of this series are as follows:

Categories, product browsing, shopping cart, settlement, CRUD (add, delete, modify, and query) management, mail, paging, model binding, authentication filters, and unit tests.

[Note] the project is developed using VS2015 + C #6. If you have any questions, please post them in the message area. Also, the page looks ugly. Sorry.

Directory

Basic addition, deletion, modification, and query CRUD

Logon authorization Filtering

Basic addition, deletion, modification, and query CRUD

We create a new controller to add, delete, modify, and query functions, AdminController, and add a method to display all data:

/// <Summary> /// background management Controller /// </summary> public class AdminController: Controller {private readonly IBookRepository _ bookRepository; public AdminController (IBookRepository bookRepository) {_ bookRepository = bookRepository;} // <summary> // home /// </summary> /// <returns> </returns> public ActionResult Index () {return View (_ bookRepository. books );}}

If the previous layout page is not followed, create a new layout page _ AdmindLayout. cshtml:

<!DOCTYPE html>

Site.css

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

Corresponding Index. cshtml:

@ Model IEnumerable <Wen. BooksStore. Domain. Entities. Book> @ {Layout = "~ /Views/Shared/_ AdminLayout. cshtml ";}< p> @ Html. actionLink ("add", "Edit ") </p> <table class = "table"> <tr> <th> name </th> <th> description </th> <th> price </th> <th> Category </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", "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 = "delete"/>}</td> </tr >}</table>

Edit. I place the ADD and edit positions in one column and use id to differentiate them. If id = 0, it indicates the newly added information.

Add the Edit Method to AdminCtroller.

/// <Summary> /// edit /// </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> /// edit /// </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 ");}

How to update a repository:

IBookRepository. cs

/// <Summary> /// book repository interface /// </summary> public interface IBookRepository {/// <summary> // book model set /// </summary> IQueryable <Book> Books {get ;} /// <summary> /// Save the book /// </summary> /// <param name = "book"> </param> /// <returns> </returns> int SaveBook (Book book ); /// <summary> /// Delete the book /// </summary> /// <param name = "id"> </param> /// <returns> </returns> Book DeleteBook (int id );}

EfBookRepository. cs

/// <Summary> /// book repository /// </summary> public class EfBookRepository: IBookRepository {private readonly EfDbContext _ context = new EfDbContext (); /// <summary> /// Book model set /// </summary> public IQueryable <Book> Books => _ context. books; /// <summary> /// Save the book /// </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> /// Delete the book /// </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 ;}}

The following features must be added to the Book Model:

[Table ("Book")] public class Book {// <summary> // Id /// </summary> public int Id {get; set ;} /// <summary> /// Name /// </summary> [Required (ErrorMessage = "Name cannot be blank")] public string Name {get; set ;} /// <summary> /// Description /// </summary> [Required (ErrorMessage = "Description cannot be blank")] public string Description {get; set ;} /// <summary> /// price /// </summary> [Required (ErrorMessage = "price cannot be blank")] [Range (0.01, double. maxValue, ErrorMessage = "please fill in the appropriate Price")] public decimal Price {get; set ;} /// <summary> /// Category /// </summary> [Required (ErrorMessage = "Category cannot be blank")] public string Category {get; set ;}}

_ AdminLayout. cshtml introduce the JavaScript code for verification (client verification ):

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

Figure: error message

Delete

/// <Summary> /// Delete /// </summary> /// <param name = "id"> </param> /// <returns> </ returns> [HttpPost] public ActionResult Delete (int id) {_ bookRepository. deleteBook (id); return RedirectToAction ("Index ");}

Add prompt. When adding, editing, and deleting, we should add the necessary prompt information and use TempData.

Add the following items in/Admin/Index. cshtml:

Execution result:

[Note] temporary TempData data stores a piece of information, which is a "key/value" dictionary, similar to Session and ViewBag. The difference between it and Session is, the HTTP request will be deleted after it is completed. Because RedirectToAction is used here, A redirection command will tell the browser to redirect requests to a new address, so ViewBag cannot be used, and ViewBag is used to transmit data between the Controller and the view, however, it cannot keep the data longer than the current HTTP request. Redirection means that the user is cross-request and ViewBag cannot be used to transmit data across requests.

Logon authorization Filtering

The above is a Admin background management operation, not every user can access the management, so now add the login authorization authentication function, only after successful, can enter the management interface.

Add the following content to the configuration file WebConfig. cs:

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

WebConfig. cs

<?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"/> 

The authorization Authentication mode used here is form authentication. In order to simplify the interaction with the database, the form of hard encoding is adopted. If you have not yet obtained the authentication, you will be directed to the Account/Login address for the Administrator to log on first. timeout indicates that the logon (authentication) Success duration is 2880 minutes (48 hours ), name indicates the user name, and password indicates the login password.

Here we use the authorization authentication filter. We need to add a [Authorize] feature to the Controller that requires authentication before it can enter, that is, to add this feature to AdminController.

Create a form Authentication provider, an interface, and an implementation:

IAuthProvider. cs:

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

FormsAuthProvider. cs:

/// <Summary> /// form Authentication provider /// </summary> public class FormsAuthProvider: IAuthProvider {// <summary> /// authentication /// </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) {// sets the authentication Cookie FormsAuthentication. setAuthCookie (userName, false);} return result ;}}

Register in the AddBindings () method:

/// <Summary> /// bind /// </summary> private void AddBindings () {_ kernel. bind <IBookRepository> (). to <EfBookRepository> (); _ kernel. bind <IOrderProcessor> (). to <EmailOrderProcessor> (); _ kernel. bind <IAuthProvider> (). to <FormsAuthProvider> ();}

/// <Summary> /// logon view model /// </summary> public class LoginViewModel {[Required (ErrorMessage = "username cannot be blank")] public string UserName {get; set;} [Required (ErrorMessage = "password cannot be blank")] [DataType (DataType. password)] public string Password {get; set ;}}

Create AccountController

Public class AccountController: Controller {private readonly IAuthProvider _ authProvider; public AccountController (IAuthProvider authProvider) {_ authProvider = authProvider ;} /// <summary> /// log on /// </summary> /// <returns> </returns> public ActionResult Login () {return View ();} /// <summary> /// log on /// </summary> /// <param name = "model"> </param> /// <returns> </ returns> [HttpPost] [ValidateAn TiForgeryToken] 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 ("", "incorrect account or user name"); return View (new LoginViewModel ());}}

Login. cshtml logon page:

@ Model Wen. BooksStore. WebUI. Models. LoginViewModel @ {Layout = null;} <! DOCTYPE html> 

[Note] the ValidateAntiForgeryToken feature is used to prevent cross-site Request Forgery (CSRF) attacks.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.