Build a CRUD Application with ASP.NET Core 2.1

Trong bài chia sẻ trước, mình có hướng dẫn các bạn việc kết nối Database và tạo Table thông qua các class, sử dụng với sự hổ trợ của EntityFramework Core
Trong bài này mình sử dụng source của bài trước! bạn có thể xem lại tại đây:Create Database using Code First in ASP.NET CORE 2.1
Bài này mình chia sẻ cách (Read,Insert,Update,Delete) trong ASP.NET Core 2.1
Đầu tiên bạn vào thư mục Models: Tạo file FormViewModels.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
namespace ShopAspCore.Models
{
    public class CreateProduct
    {
        [Required(ErrorMessage ="Enter title!")]
        public string Title { get; set; }
        [Required(ErrorMessage ="Choose image")]
        public IFormFile UrlImage { get; set; }
        [Required(ErrorMessage ="Enter price")]
        public string Price { get; set; }
        [Required(ErrorMessage ="Enter detail")]
        public string Detail { get; set; }
        [Required(ErrorMessage ="Choose category")]
        public int idCategory { get; set; }
    }
}

Trong file FormViewModels.cs bên trên, mình có tạo một class tên là CreateProduct, class này mình cấu hình các thuộc tính để hồi ta sử dụng trong Form tạo product, bạn có thể tạo nhiều class trong đây nhé, để tiện cho việc sử dụng
[Required(ErrorMessage ="Enter title!")]: Required bất buộc trường thuộc tính đó phải nhập, nếu không nhập sẽ hiển thị lỗi đó ra
IFormFile UrlImage: mình chỉ định nó là một dạng file, các bạn có thể không cần cũng được có thể dùng kiểu string

Ok. giờ ta vào thư mục Controllers->add file ProductController.cs

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using ShopAspCore.Models;

namespace ShopAspCore.Controllers
{
    public class ProductController : Controller
    {
        private EFDataContext _db;
        private readonly IHostingEnvironment _appEnvironment;
        public ProductController(EFDataContext db, IHostingEnvironment appEnvironment)
        {
            _db = db;
            _appEnvironment = appEnvironment;
        }
        // GET: Product
        public ActionResult Index()
        {
            var data = _db.Products.Select(s => new Product
            {
                idProduct = s.idProduct,
                Title = s.Title,
                Price = s.Price,
                UrlImage = s.UrlImage,
                Detail = s.Detail,
                idCategory = s.idCategory,
                Category = _db.Categories.Where(a=>a.idCategory==s.idCategory).FirstOrDefault()

            }).ToList();
            return View(data);
        }

        // GET: Product/Create
        public ActionResult Create()
        {
            CategoryDropDownList();
            return View();
        }

        // POST: Product/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create(CreateProduct _product)
        {
            if (ModelState.IsValid)
            {
                string UrlImage = "";
                var files = HttpContext.Request.Form.Files;
                foreach (var Image in files)
                {
                    if (Image != null && Image.Length > 0)
                    {
                        var file = Image;
                        
                        var uploads = Path.Combine(_appEnvironment.WebRootPath, "images");
                        if (file.Length > 0)
                        {
                           // var fileName = Guid.NewGuid().ToString().Replace("-", "") + Path.GetExtension(file.FileName);
                            var fileName = Guid.NewGuid().ToString().Replace("-", "") + file.FileName;
                            using (var fileStream = new FileStream(Path.Combine(uploads, fileName), FileMode.Create))
                            {
                                await file.CopyToAsync(fileStream);
                                UrlImage = fileName;
                            }

                        }
                    }
                }
                var data = new Product()
                {
                    Title = _product.Title,
                    UrlImage = UrlImage,
                    Price = _product.Price,
                    Detail = _product.Detail,
                    idCategory = _product.idCategory
                };
                _db.Products.Add(data);
                await _db.SaveChangesAsync();
                return RedirectToAction(nameof(Index));

            }
            CategoryDropDownList();
            return View();
        }

        // GET: Product/Edit/5
        public ActionResult Edit(int id)
        {
            var product = _db.Products.Find(id);
            CategoryDropDownList();
            return View(product);
        }

        // POST: Product/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit(int id,Product _product)
        {
            if (ModelState.IsValid)
            {
                string UrlImage = "";
                var files = HttpContext.Request.Form.Files;
                foreach (var Image in files)
                {
                    if (Image != null && Image.Length > 0)
                    {
                        var file = Image;
                    
                        var uploads = Path.Combine(_appEnvironment.WebRootPath, "images");
                        if (file.Length > 0)
                        {
                            // var fileName = Guid.NewGuid().ToString().Replace("-", "") + Path.GetExtension(file.FileName);
                            var fileName = Guid.NewGuid().ToString().Replace("-", "") + file.FileName;
                            using (var fileStream = new FileStream(Path.Combine(uploads, fileName), FileMode.Create))
                            {
                                await file.CopyToAsync(fileStream);
                                UrlImage = fileName;
                            }

                        }
                    }
                }
                var data = _db.Products.Find(id);
                data.Title = _product.Title;
                data.Price = _product.Price;
                data.Detail = _product.Detail;
                data.UrlImage = UrlImage;
                data.idCategory = _product.idCategory;
                await _db.SaveChangesAsync();
                //  return RedirectToAction(nameof(Edit), new { id = data.idProduct });
                return RedirectToAction(nameof(Index));

            }
            CategoryDropDownList();
            return View();
        }

        // GET: Product/Delete/5
        public async Task<ActionResult> Delete(int id)
        {
            var data = _db.Products.Find(id);
            _db.Products.Remove(data);
            await _db.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        private void CategoryDropDownList(object categorySelect = null)
        {
            var rolesQuery = _db.Categories.ToList();
            ViewBag.Categories = new SelectList(rolesQuery, "idCategory", "Name", categorySelect);
        }
    }
}

Với đoạn code bên trên mình nghĩ các bạn cũng hình dung ra rằng, đầu tiên ta cần khai báo EFDataContext để có thể kết nói tới database của ta, và thực hiện các câu lệnh truy vấn LinQ
CategoryDropDownList(): dùng cho việc lấy toàn bộ dữ liệu category để show ra việc (thêm, sửa) có thể chọn lựa
Chúng ta cần dùng System.IO: để có thể đọc file 
_appEnvironment.WebRootPath: lấy đường dẫn mặc định thư mục wwwroot,bạn hãy đảm bảo rằng trong file Startup.cs bạn có thêm app.UseStaticFiles();

Okay, vậy là xong rồi! giờ ta chỉ việt viết tạo view để hiện thị các chức năng thôi

+ Views/Product/Index.cshtml

@model IEnumerable<Product>
@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
    <div class="col-md-8">
        <h2>List Product</h2>
        <a asp-controller="Product" asp-action="Create" class="btn btn-primary">Add Product</a>
        <table class="table">
            <thead>
                <tr>
                    <th>STT</th>
                    <th>Title</th>
                    <th>UrlImage</th>
                    <th>Price</th>
                    <th>Detail</th>
                    <th>Category</th>
                    <th>Edit</th>
                    <th>Delete</th>
                </tr>
            </thead>
            <tbody>
                @{ 
                    int stt = 0;
                    foreach(var item in Model)
                    {
                        stt++;
                                <tr>
                                    <td>@stt</td>
                                    <td>@item.Title</td>
                                    <td><img src="~/images/@item.UrlImage" width="80" height="80" /></td>
                                    <td>@item.Price</td>
                                    <td>@item.Detail</td>
                                    <td>@item.Category.Name</td>
                                    <td><a asp-controller="Product" asp-action="Edit"  asp-route-id="@item.idProduct" class="badge bg-warning">Edit</a></td>
                                    <td><a asp-controller="Product" asp-action="Delete" asp-route-id="@item.idProduct" class="badge bg-danger">Delete</a></td>
                                </tr>
                    }
                }
            </tbody>
        </table>
    </div>
</div>

Build a CRUD Application with ASP.NET Core 2.1

+ Views/Product/Create.cshtml

@model ShopAspCore.Models.CreateProduct
@{
    ViewData["Title"] = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

    <div class="row">
        <div class="col-md-8">
            <h2>CREATE PRODUCT</h2>
            <form asp-controller="Product" asp-action="Create" method="post" enctype="multipart/form-data">
                @Html.AntiForgeryToken()
                <div class="form-group">
                    <label>Title</label>
                    <input asp-for="Title" class="form-control" />
                    <span asp-validation-for="Title" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label>UrlImage</label>
                    <input type="file" asp-for="UrlImage" class="form-control" />
                    <span asp-validation-for="UrlImage" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label>Price</label>
                    <input asp-for="Price" class="form-control" />
                    <span asp-validation-for="Price" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label>Detail</label>
                    <input asp-for="Detail" class="form-control" />
                    <span asp-validation-for="Detail" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label>Category</label>
                    <select asp-for="idCategory" asp-items="@ViewBag.Categories" class="form-control">
                        <option value="">Select Category</option>
                    </select>
                    <span asp-validation-for="idCategory" class="text-danger"></span>
                </div>
                <div class="form-group">
                   <input type="submit" name="submit" value="Add Product" class="btn btn-primary"/>
                </div>
            </form>
        </div>
    </div>

Đoạn code trên các bạn xem phần select option của mình, mình dùng asp-items="" để lập các dữ liệu của category ra option nhé

+ Views/Product/Edit.cshtml

@model Product
@{
    ViewData["Title"] = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
    <div class="col-md-8">
        <h2>EDIT PRODUCT</h2>
        <form asp-controller="Product" asp-action="Edit" method="post" enctype="multipart/form-data">
            @Html.AntiForgeryToken()
            <div class="form-group">
                <label>Title</label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>UrlImage</label>
                <img src="~/images/@Model.UrlImage" width="80" height="80" class="change_edit"/>
                <input type="file" asp-for="UrlImage" class="form-control changeImage" />
                <span asp-validation-for="UrlImage" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Price</label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Detail</label>
                <input asp-for="Detail" class="form-control" />
                <span asp-validation-for="Detail" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Category</label>
                <select asp-for="idCategory" asp-items="@ViewBag.Categories" class="form-control">
                    <option value="">Select Category</option>
                </select>
                <span asp-validation-for="idCategory" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" name="submit" value="Add Product" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>
<script src="~/js/jquery.min.js"></script>
<script type="text/javascript">

        $(function(){
          $('.changeImage').change(function(){
            var input = this;
            var url = $(this).val();
            var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
            if (input.files && input.files[0]&& (ext == "gif" || ext == "png" || ext == "jpeg" || ext == "jpg")) 
             {
                var reader = new FileReader();

                reader.onload = function (e) {
                   $('.change_edit').attr('src', e.target.result);
                }
               reader.readAsDataURL(input.files[0]);
            }
            else
            {
              $('.change_edit').attr('src', '/images/@Model.UrlImage');
            }
          });

        });
</script>

Trong đoạn code Edit.cshtml của mình, có viết thêm một đoạn javascript, đoạn code đó dùng để chọn hình ảnh khi ta thay đổi

Ok, xong rồi bạn có thể build project lên và chạy thử hoặc bạn mở cmd trong trong project và chạy các câu lệnh sau

dotnet build
dotnet run

Sau đó bạn gõ địa chỉ https://localhost:5001 lên trình duyệt và thử nghiệm nó!

Bài Viết Liên Quan

Messsage

Ủng hộ tôi bằng cách click vào quảng cáo. Để tôi có kinh phí tiếp tục phát triển Website!(Support me by clicking on the ad. Let me have the money to continue developing the Website!)