2013年8月18日 星期日

效能大戰首部曲 - 快速開發篇 ASP.NET MVC 使用 PartialView 實作 Treeview

雖然主題是效能,但是本篇沒有任何跟效能有關的內容,只是介紹專案如何快速開發出原形(之後效能實驗用的專案)





建立方案 Massive

建立專案 Console 主控台應用程式 - 塞資料/測試 DB 用

建立專案 Repository 類別庫 - ORM DB Layer

建立專案 MvcApplication ASP.NET MVC 4 Web 應用程式(網際網路應用程式) - MVC 站台

建立專案 WebApplication ASP.NET Web Form Web 應用程式(網際網路應用程式) - WebForm 站台

然後去內臟...不,是把沒用的一些檔案砍了 因為這兩個 web 專案都很好心雞婆的附上會員機制





建立資料庫 TABLE 大致如下

於 Repository 建立 ADO.NET 實體資料模型





利用 MVC 的 scaffold template 快速產出 CRUD 原形 (Controllers & Views)

(如果跳出什麼連線字串的警告就手動把 Repository App.Config 裡面的連線字串複製到 web 專案的 Web.config)

然後將 Controllers 的 DB Layer 抽離至 Repository 供全部專案使用

這邊 Web Form 就比較麻煩些 沒有方便的 scaffold 產出頁面 (visual studio 2013 就有了,等不及的去抓 preview 吧 ~.~)

但是這難不倒 PG<F2E> 泛型設計師 就把 MVC 的 CHTML 模仿一下到 Web Form

顯示資料的 TABLE 改成 GridView 即可(頁面呈現的方式在後面幾部曲會詳細討論)

這裡先挑軟柿子 Department 整理

MvcApplication/Content/DepartmentController.cs

using Repository;
using System;
using System.Web.Mvc;

namespace MvcApplication.Controllers
{
    public class DepartmentController : Controller
    {
        private DepartmentRepository departmentRepository = new DepartmentRepository();

        #region GET

        //LIST
        public ActionResult Index()
        {
            return View(departmentRepository.GetAllDepartment());
        }

        //Detail
        public ActionResult Details(int id = 0)
        {
            return GetDepartment(id);
        }

        //Edit
        public ActionResult Edit(int id = 0)
        {
            return GetDepartment(id);
        }

        //Delete confirm
        public ActionResult Delete(int id = 0)
        {
            return GetDepartment(id);
        }

        private ActionResult GetDepartment(int id)
        {
            Department department = departmentRepository.GetDepartmentByID(id);
            if (department == null)
            {
                return HttpNotFound();
            }
            return View(department);
        }

        //Create
        public ActionResult Create()
        {
            return View();
        }

        #endregion GET

        #region POST

        //Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Department department)
        {
            return Save(department, () =>
            {
                departmentRepository.AddDepartment(department);
            });
        }

        //Edit
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Department department)
        {
            return Save(department, () =>
            {
                departmentRepository.ModifiedDepartment(department);
            });
        }

        private ActionResult Save(Department department, Action action)
        {
            if (ModelState.IsValid)
            {
                action();
                return RedirectToAction("Index");
            }
            return View(department);
        }

        //Delete
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            departmentRepository.RemoveDepartment(id);
            return RedirectToAction("Index");
        }

        #endregion POST

        protected override void Dispose(bool disposing)
        {
            departmentRepository.Dispose();
            base.Dispose(disposing);
        }
    }

}

Repository/DepartmentRepository.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace Repository
{
    public class DepartmentRepository : IDisposable
    {
        private MassiveEntities db = new MassiveEntities();

        public IEnumerable<Department> GetAllDepartment()
        {
            return db.Department.ToList();
        }

        public Department GetDepartmentByID(int id = 0)
        {
            return db.Department.Find(id);
        }

        public Department AddDepartment(Department department)
        {
            var result = db.Department.Add(department);
            db.SaveChanges();
            return result;
        }

        public Department ModifiedDepartment(Department department)
        {
            db.Entry(department).State = EntityState.Modified;
            db.SaveChanges();
            return department;
        }

        public Department RemoveDepartment(int id)
        {
            Department department = db.Department.Find(id);
            var result = db.Department.Remove(department);
            db.SaveChanges();
            return result;
        }

        public void Dispose()
        {
            db.Dispose();
        }
    }

}




但是即使整理完了 DepartmentController 雖然的確可以 CRUD 但是有點不敷使用啊

(WTF is it...)

這種階層式的資料 很自然會想弄成 treeview 的形式

做法當然千奇百怪都有 這邊我們以 PartialView 來實作





TreeViewNode 類用來實作 TreeView 結構的資料

DepartmentController 主要修改 Index 的部分 使用遞迴 填充 TreeViewNode

DepartmentRepository 主要修改 RemoveDepartment 刪除會連同子結點一併刪除

Node.cshtml PartialView(部分檢視) 用來實現 TreeViewNode 的 HTML

Index.cshtml 原本的 List 頁面 改用 Node.cshtml 來呈現

原本的 Create 頁 改為 Add 沒什麼特別原因 只是個人喜好

Edit 原本 ParentID 用 TextBox 輸入 改為 DropDownList 用挑的

Details 沒啥變 ParentID 改為顯示 ParentDepartmentName

Delete 同 Details

最後玩弄的效果

沒有留言:

張貼留言