TOC

This article is currently in the process of being translated into Vietnamese (~70% done).

Working with databases:

TODO List: The Controller

Trong ví dụ trước, chúng ta đã thiết lập cơ sở dữ liệu cho ứng dụng web TODO list. Chúng ta thêm vào một Model, một ViewModel và một lớp Helper và một View để hiển thị list. Giờ là lúc liên kết chúng với nhau: Controller.

The Controller

Ứng dụng web TODO list chỉ có một mục đích duy nhất: là TODO List! Vì vậy, chúng ta chỉ cần một controller là HomeController. Trong ứng dụng lớn hơn, nó có thể gọi là TodoController hay TodoListController, nhưng khi gọi nó là HomeController thì chúng ta có thể truy cập vào view Index (cũng chỉ cần một View) từ gốc của ứng dụng web.

Controller của chúng ta có nhiều action cho phép ta thêm một item vào TODO list cũng như cập nhật hay xóa một item có sẵn. Toàn bộ action đều có phương thức của riêng chúng, có kèm giải thích, và tôi sẽ đi lần lượt qua tất cả các phương thức và sau đó bạn sẽ có toàn bộ Controller ở phần cuối.

Index():

public IActionResult Index()
{
    TodoListViewModel viewModel = new TodoListViewModel();    
    return View("Index", viewModel);
}

Không có nhiều thứ ở đây. Vì TODO List chỉ có một View. Vì View dùng TodoListViewModel, chúng ta tạo ra một thể hiện của chúng ở đây (để tải các item trong TODO list, như mô tả trong bài trước) và sau đó chúng ta truyền chúng vào view dùng phương thức View().

Edit():

public IActionResult Edit(int id)
{
    TodoListViewModel viewModel = new TodoListViewModel();
    viewModel.EditableItem = viewModel.TodoItems.FirstOrDefault(x => x.Id == id);
    return View("Index", viewModel);
}

Action Edit() giống action Index(), ngoại trừ ở dòng giữa, nơi mà chúng ta gán thuộc tính EditableItem cho item được yêu cầu bởi người dùng thông qua tham số id. Chúng ta sử dụng cùng View (Index).

Delete():

public IActionResult Delete(int id)
{
    using(var db = DbHelper.GetConnection())
    {
TodoListItem item = db.Get<TodoListItem>(id);
if(item != null)
    db.Delete(item);
return RedirectToAction("Index");
    }
}

Phương thức Delete(), giống phương thức Edit(), lấy một tham số gọi là id - với tham số này, bạn có thể truy cập vào item trong cơ sở dữ liệu (dùng phương thức Get() từ Dapper.Contrib), sau đó chúng ta gọi phương thức Delete()(cũng từ Dapper.Contrib). Đây là một minh họa dễ hiểu về cách dùng Dapper và Dapper.Contrib để viết SQL cho việc lấy và xóa dữ liệu.

CreateUpdate():

public IActionResult CreateUpdate(TodoListViewModel viewModel)
{
    if(ModelState.IsValid)
    {
using(var db = DbHelper.GetConnection())
{
    if(viewModel.EditableItem.Id <= 0)
    {
viewModel.EditableItem.AddDate = DateTime.Now;
db.Insert<TodoListItem>(viewModel.EditableItem);
    }
    else
    {
TodoListItem dbItem = db.Get<TodoListItem>(viewModel.EditableItem.Id);
var result = TryUpdateModelAsync<TodoListItem>(dbItem, "EditableItem");
db.Update<TodoListItem>(dbItem);
    }
}
return RedirectToAction("Index");
    }
    else
return View("Index", new TodoListViewModel());        
}

Action phức tạp nhất trong Controller là CreateUpdate(). Vì FORM trong View được dùng cho cả thêm và cập nhật item nên action này cần phải xử lý được cả hai.

Điều đầu tiên cần là kiểm tra thuộc tính ModelState.IsValid - cho phép chúng ta biết liệu Model có hợp lệ hay không tùy thuộc vào kiểm tra tính hợp lệ của model mà chúng ta có trong bài trước. Nếu nó là hợp lệ thì chúng ta gọi phương thức View() và chỉ hiển thị view Index - tuy nhiên, ModelState sẽ giúp cho việc hiển thị validation summary trên View, để kiểm soát lỗi của Model.

Nếu Model là hợp lệ thì chúng ta kiểm tra thuộc tính Id của EditableItem - nếu nó không lớn hơn 0 thì chúng ta thêm mới một item. Chúng ta chỉ gán giá trị DateTime hiện tại vào thuộc tính AddDate() và sau đó gọi phương thức Insert() để thêm một item mới vào cơ sở dữ liệu.

Nếu Id lớn hơn 0 thì chúng ta làm việc với item đã tồn tại. Chúng ta lấy item từ cơ sở dữ liệu và sau đó gọi TryUpdateModelAsinc(). Nó sẽ cập nhật đối tượng chúng ta có trong cơ sở dữ liệu với giá trị trong Model đưa tới server, trong trường hợp này chỉ là thuộc tính Title. Một khi model đã được cập nhât thì chúng ta thay đổi trong cơ sở dữ liệu bằng phương thức Update().

When all this is done, we simply do a redirect to the Index action, essentially returning everything to the way it was before. The changes made will automatically be reflected when the Index action is called and the ViewModel is loaded. Be aware that we don't do any error checking or exception handling during this process, to keep the example as compact as possible - you should of course, as a minimum, handle any possible exception in a real-world application.

ToggleIsDone:

public IActionResult ToggleIsDone(int id)
{
    using(var db = DbHelper.GetConnection())
    {
TodoListItem item = db.Get<TodoListItem>(id);
if(item != null)
{
    item.IsDone = !item.IsDone;
    db.Update<TodoListItem>(item);
}
return RedirectToAction("Index");
    }
}

We activate this action with a small piece of JavaScript found in our View. It will simply fetch the TodoListItem specified by the id parameter, using the Get() method on the database. Once we have the the item, we change the IsDone to be False if it's currently True and vice versa. As soon as we have done that, we update the corresponding row in the database, using the Update() method.

That was the final method in our Controller. As promised, here's the full code listing:

using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using TodoList.Models;
using Dapper;
using Dapper.Contrib.Extensions;
using TodoList.ViewModels;
using TodoList.Helpers;

namespace TodoList.Controllers
{
    public class HomeController : Controller
    {
public IActionResult Index()
{
    TodoListViewModel viewModel = new TodoListViewModel();    
    return View("Index", viewModel);
}

public IActionResult Edit(int id)
{
    TodoListViewModel viewModel = new TodoListViewModel();
    viewModel.EditableItem = viewModel.TodoItems.FirstOrDefault(x => x.Id == id);
    return View("Index", viewModel);
}

public IActionResult Delete(int id)
{
    using(var db = DbHelper.GetConnection())
    {
TodoListItem item = db.Get<TodoListItem>(id);
if(item != null)
    db.Delete(item);
return RedirectToAction("Index");
    }
}

public IActionResult CreateUpdate(TodoListViewModel viewModel)
{
    if(ModelState.IsValid)
    {
using(var db = DbHelper.GetConnection())
{
    if(viewModel.EditableItem.Id <= 0)
    {
viewModel.EditableItem.AddDate = DateTime.Now;
db.Insert<TodoListItem>(viewModel.EditableItem);
    }
    else
    {
TodoListItem dbItem = db.Get<TodoListItem>(viewModel.EditableItem.Id);
TryUpdateModelAsync<TodoListItem>(dbItem, "EditableItem");
db.Update<TodoListItem>(dbItem);
    }
}
return RedirectToAction("Index");
    }
    else
return View("Index", new TodoListViewModel());        
}

public IActionResult ToggleIsDone(int id)
{
    using(var db = DbHelper.GetConnection())
    {
TodoListItem item = db.Get<TodoListItem>(id);
if(item != null)
{
    item.IsDone = !item.IsDone;
    db.Update<TodoListItem>(item);
}
return RedirectToAction("Index");
    }
}
    }
}

Summary

Congratulations, you have just built your very own database-driven TODO List web application! Now add some items to it, click on the title to edit the item, click on the checkbox to toggle the IsDone property or click the Delete button to remove an item. All changes will be reflected in the database and be visible the next time you load the page - awesome!


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!