網頁

2014年6月23日 星期一

ASP.NET MVC 5 with CheckboxList 應用範例

前一陣子完成了「ASP.NET MVC - CheckBoxList 與 ValidationMessage (ASP.NET MVC 5 with Bootstrap3)」與「ASP.NET MVC - CheckBoxList 與 ValidationMessage (ASP.NET MVC 4 without Bootstrap)」這兩篇有關於 CheckBoxList 與 ASP.NET MVC ValidationMessage 的應用,但這兩篇文章與之前有關 CheckBoxList 的文章都只有展示 CheckBoxList 的功能,並沒有實際針對在資料的 CRUD(Create, Read, Update, Delete)操作上去怎麼使用,所以這一篇文章就來說明怎麼在資料的 CRUD 操作去使用 CheckBoxList。

 


開發環境:Visual Studio 2013 Update 2 , LocalDB , ASP.NET MVC 5 , Entity Framework 6.1.0

 

建立一個 ASP.NET MVC 5 專案

image

 

Foobar

這是我們要進行 CRUD 處理的 Table,而其中 Categories 欄位所要儲存的是 Northwind 的 Category 的 ID 編號,多個 Category ID 將會用「,」逗號分隔,

image

 

ViewModel

這邊建立 View 與 Controller 所使用的 ViewModel 類別,將原本 EF 所建立 Foobar 類別再另外建立 Partial Class 以及 MetadataType Class,

image

using System;
using System.ComponentModel.DataAnnotations;
 
namespace WebApplication1.Models
{
    [MetadataType(typeof(FoobarMetadata))]
    public partial class Foobar
    {
        public class FoobarMetadata
        {
            [Display(Name = "編號")]
            [Required(ErrorMessage = "為必要欄位")]
            public Guid ID { get; set; }
 
            [Display(Name = "名稱")]
            [Required]
            [StringLength(100, ErrorMessage = "請輸入名稱")]
            public string Name { get; set; }
 
            [Display(Name = "分類")]
            [Required(ErrorMessage = "請至少選擇一個分類")]
            public string Categories { get; set; }
 
            [Display(Name = "建立日期")]
            [Required(ErrorMessage = "為必要欄位")]
            public DateTime CreateDate { get; set; }
 
            [Display(Name = "更新日期")]
            [Required(ErrorMessage = "為必要欄位")]
            public DateTime UpdateDate { get; set; }
 
        }
 
        public string SelectedCategories { get; set; }
 
    }
}

 

Service

再來建立 FoobarService,

image

using System;
using System.Linq;
using WebApplication1.Infrastructure.Repository;
using WebApplication1.Models;
 
namespace WebApplication1.Infrastructure.Services
{
    public class FoobarService
    {
        private IRepository<Foobar> _Repository = new DataRepository<Foobar>();
 
        public void Create(Foobar instance)
        {
            if(instance == null)
            {
                throw new ArgumentNullException("instance", "null");
            }
            instance.ID = Guid.NewGuid();
            instance.CreateDate = DateTime.Now;
            instance.UpdateDate = DateTime.Now;
 
            this._Repository.Add(instance);
            this._Repository.SaveChanges();
        }
 
        public void Delete(Guid id)
        {
            var instance = this.GetOne(id);
            if (instance == null)
            {
                throw new InvalidOperationException("not found");
            }
 
            this._Repository.Delete(instance);
            this._Repository.SaveChanges();
        }
 
        public void Update(Foobar instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance", "null");
            }
 
            instance.UpdateDate = DateTime.Now;
 
            this._Repository.Update(instance);
            this._Repository.SaveChanges();
        }
 
        public bool IsExists(Guid id)
        {
            return this._Repository.IsExists(x => x.ID == id);
        }
 
        public Foobar GetOne(Guid id)
        {
            return this._Repository.FirstOrDefault(x => x.ID == id);
        }
 
        public IQueryable<Foobar> GetAll()
        {
            return this._Repository.FindAll().OrderByDescending(x => x.CreateDate);
        }
 
 
    }
}

 

FoobarController

image

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using WebApplication1.Infrastructure.Services;
using WebApplication1.Models;
 
namespace WebApplication1.Controllers
{
    public class FoobarsController : Controller
    {
        private FoobarService foobarService = new FoobarService();
        private CategoryService categoryService = new CategoryService();
 
        private List<SelectListItem> CategorySelectListItems(string selected = "")
        {
            var categories = this.categoryService.GetAll();
            var items = new List<SelectListItem>();
 
            var selectedCategories = string.IsNullOrWhiteSpace(selected)
                ? null
                : selected.Split(',');
 
            foreach (var c in categories)
            {
                items.Add(item: new SelectListItem()
                {
                    Value = c.CategoryID.ToString(),
                    Text = c.CategoryName,
                    Selected = selectedCategories == null
                        ? false
                        : selectedCategories.Contains(c.CategoryID.ToString())
                });
            }
            return items;
        }
 
        public ActionResult Index()
        {
            var foobars = this.foobarService.GetAll();
            var categories = this.CategorySelectListItems();
 
            var result = new List<Foobar>();
            foreach ( var item in foobars )
            {
                var selectedList = item.Categories.Split(',').ToList();
                item.SelectedCategories = string.IsNullOrWhiteSpace(item.Categories)
                    ? ""
                    : string.Join(
                        ",",
                        categories.Where(x => selectedList.Contains(x.Value)).Select(x => x.Text));
 
                result.Add(item);
            }
 
            return View(result.ToList());
        }
 
        public ActionResult Details(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Foobar foobar = this.foobarService.GetOne(id.Value);
            if (foobar == null)
            {
                return HttpNotFound();
            }
 
            var items = this.CategorySelectListItems(foobar.Categories);
            foobar.SelectedCategories = string.IsNullOrWhiteSpace(foobar.Categories)
                ? ""
                : string.Join(",", items.Where(x => x.Selected).Select(x => x.Text)); 
 
            return View(foobar);
        }
 
        public ActionResult Create()
        {
            var items = this.CategorySelectListItems();
            ViewBag.CategoryItems = items;
 
            return View();
        }
 
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(string name, string[] categories)
        {
            var foobar = new Foobar
            {
                Name = name,
                Categories = string.Join(",", categories)
            };
 
            if (ModelState.IsValid)
            {
                this.foobarService.Create(foobar);
                return RedirectToAction("Index");
            }
 
            var items = this.CategorySelectListItems();
            ViewBag.CategoryItems = items;
 
            return View(foobar);
        }
 
        public ActionResult Edit(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Foobar foobar = this.foobarService.GetOne(id.Value);
            if (foobar == null)
            {
                return HttpNotFound();
            }
 
            var items = this.CategorySelectListItems(foobar.Categories);
            ViewBag.CategoryItems = items;
 
            return View(foobar);
        }
 
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Guid id, string name, string[] categories)
        {
            var foobar = this.foobarService.GetOne(id);
            if (foobar == null)
            {
                return RedirectToAction("Index");
            }
 
            if (ModelState.IsValid)
            {
                foobar.Name = name;
                foobar.Categories = string.Join(",", categories);
                this.foobarService.Update(foobar);
 
                return RedirectToAction("Index");
            }
 
            var items = this.CategorySelectListItems();
            ViewBag.CategoryItems = items;
 
            return View(foobar);
        }
 
        public ActionResult Delete(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Foobar foobar = this.foobarService.GetOne(id.Value);
            if (foobar == null)
            {
                return HttpNotFound();
            }
 
            var items = this.CategorySelectListItems(foobar.Categories);
            foobar.SelectedCategories = string.IsNullOrWhiteSpace(foobar.Categories)
                ? ""
                : string.Join(",", items.Where(x => x.Selected).Select(x => x.Text)); 
 
            return View(foobar);
        }
 
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(Guid id)
        {
            bool isExists = this.foobarService.IsExists(id);
            if (!isExists)
            {
                return RedirectToAction("Index");
            }
            this.foobarService.Delete(id);
            return RedirectToAction("Index");
        }
    }
}

 

Views

在 Create 與 Edit 的 View 原始碼裡,要特別注意的是最底下的Javascript Code,可千萬別忘了。

Create.cshtml

@using WebApplication1.Infrastructure.Enums
@model WebApplication1.Models.Foobar
 
@{
    ViewBag.Title = "Create";
}
 
<h2>Create</h2>
 
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
 
    <div class="form-horizontal">
        <h4>Foobar</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.Categories, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @*@Html.EditorFor(model => model.Categories, new { htmlAttributes = new { @class = "form-control" } })*@
                @*@Html.ValidationMessageFor(model => model.Categories, "", new { @class = "text-danger" })*@
 
                @Html.EditorFor(model => model.Categories,
                    "CheckBoxList",
                    new
                    {
                        TagName = "Categories",
                        CheckBoxItems = ViewBag.CategoryItems,
                        Position = Position.Vertical,
                        Numbers = 3
                    })
            </div>
        </div>
 
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
 
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
 
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript">
        $(function () {
            $('input[name="Categories"]').rules('add', {
                messages: {
                    required: "請至少選擇一個分類"
                }
            });
        });
    </script>
}
 

Edit.cshtml

@using WebApplication1.Infrastructure.Enums
@model WebApplication1.Models.Foobar
 
@{
    ViewBag.Title = "Edit";
}
 
<h2>Edit</h2>
 
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
 
    <div class="form-horizontal">
        <h4>Foobar</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.ID)
 
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.Categories, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @*@Html.EditorFor(model => model.Categories, new { htmlAttributes = new { @class = "form-control" } })*@
                @*@Html.ValidationMessageFor(model => model.Categories, "", new { @class = "text-danger" })*@
                @Html.EditorFor(model => model.Categories,
                    "CheckBoxList",
                    new
                    {
                        TagName = "Categories",
                        CheckBoxItems = ViewBag.CategoryItems,
                        Position = Position.Vertical,
                        Numbers = 3
                    })
 
            </div>
        </div>
 
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}
 
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
          
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript">
        $(function () {
            $('input[name="Categories"]').rules('add', {
                messages: {
                    required: "請至少選擇一個分類"
                }
            });
        });
    </script>
}

 

執行結果

Index (List)

image

Create

image

Details

image

Edit

image

Delete

image

 


文章內容的程式範例已經上傳到 GitHub,想要查看程式細節或是下載範例程式的朋友請自行前往。

GitHub Repository

MVC5_with_CheckBoxList_CRUD

image

 

以上

沒有留言:

張貼留言