前一陣子完成了「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 專案
Foobar
這是我們要進行 CRUD 處理的 Table,而其中 Categories 欄位所要儲存的是 Northwind 的 Category 的 ID 編號,多個 Category ID 將會用「,」逗號分隔,
ViewModel
這邊建立 View 與 Controller 所使用的 ViewModel 類別,將原本 EF 所建立 Foobar 類別再另外建立 Partial Class 以及 MetadataType Class,
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,
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
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)
Create
Details
Edit
Delete
文章內容的程式範例已經上傳到 GitHub,想要查看程式細節或是下載範例程式的朋友請自行前往。
GitHub Repository
以上
沒有留言:
張貼留言