前言:好久沒更新部落格了,每天被該死的業務纏身,今天正好一個模組完成了,繼續來完善我們的程式碼。之前的六篇完成了領域層、應用層、以及基礎結構層的部分程式碼,這篇打算搭建下UI層的程式碼。
一、UI層介紹
在DDD裡面,UI層的設計也分為BS和CS,本篇還是以Web為例來說明。我們的Web採用的是MVC+bootstrap的架構。Table元件使用的是bootstrap table,之所以用它是因為它的API比較全,並且博主覺得它的風格適用於各種型別的裝置,無論是PC端還是手機端都都能很好的相容各種瀏覽器。
這裡還是貼出bootstrap API的相關地址。
Bootstrap中文網:http://www.bootcss.com/
Bootstrap Table Demo:http://issues.wenzhixin.net.cn/bootstrap-table/index.html
Bootstrap Table API:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/
Bootstrap Table原始碼:https://github.com/wenzhixin/bootstrap-table
Bootstrap DataPicker:http://www.bootcss.com/p/bootstrap-datetimepicker/
二、程式碼示例
上篇完成了WCF的設計程式碼,但是具體的業務邏輯的程式碼還沒有,我們先來實現具體業務的CURD程式碼。
1、WCF程式碼
1.1 WCF服務業務介面程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
/// /// 許可權管理模組介面契約 /// [ServiceContract] [ServiceInterface] public interface IPowerManageWCFService { #region 使用者管理 [OperationContract] List GetUsers(ExpressionNode expressionNode); [OperationContract] DTO_TB_USERS AddUser(DTO_TB_USERS oUser); [OperationContract] bool DeleteUser(DTO_TB_USERS oUser); [OperationContract] bool DeleteUserByLamada(ExpressionNode expressionNode); [OperationContract] bool UpdateUser(DTO_TB_USERS oUser); #endregion #region 部門管理 [OperationContract] List GetDepartments(ExpressionNode expressionNode); [OperationContract] DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept); [OperationContract] bool DeleteDepartment(DTO_TB_DEPARTMENT oDept); [OperationContract] bool DeleteDeptByLamada(ExpressionNode expressionNode); [OperationContract] bool UpdateDepartment(DTO_TB_DEPARTMENT oDept); #endregion #region 角色管理 [OperationContract] List GetRoles(ExpressionNode expressionNode); [OperationContract] DTO_TB_ROLE AddRole(DTO_TB_ROLE oRole); #endregion #region 選單管理 [OperationContract] List GetMenus(ExpressionNode expressionNode); [OperationContract] DTO_TB_MENU AddMenu(DTO_TB_MENU oMenu); #endregion } |
1.2 WCF介面實現程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
[ServiceClass] public class PowerManageWCFService :BaseService, IPowerManageWCFService { #region Fields [Import] private IUserRepository userRepository { get; set; } [Import] private IDepartmentRepository departmentRepository { get; set; } [Import] private IRoleRepository roleRepository { get; set; } [Import] private IMenuRepository menuRepository { get; set; } #endregion #region Constust public PowerManageWCFService() { } #endregion #region WCF服務介面實現 #region 使用者管理 //這裡引數為什麼不直接用Expression>這種型別,是因為Expression不支援序列化,無法用於WCF資料的傳遞 public List GetUsers(ExpressionNode expressionNode) { Expressionbool>> selector = null; if (expressionNode != null) { selector = expressionNode.ToExpressionbool>>(); } var lstRes = base.GetDtoByLamada(userRepository, selector); return lstRes; } public DTO_TB_USERS AddUser(DTO_TB_USERS oUser) { return base.AddDto(userRepository, oUser); } public bool DeleteUser(DTO_TB_USERS oUser) { var bRes = false; try { base.DeleteDto(userRepository, oUser); bRes = true; } catch { } return bRes; } public bool DeleteUserByLamada(ExpressionNode expressionNode) { Expressionbool>> selector = null; if (expressionNode != null) { selector = expressionNode.ToExpressionbool>>(); } var bRes = false; try { base.DeleteDto(userRepository, selector); bRes = true; } catch { } return bRes; } public bool UpdateUser(DTO_TB_USERS oUser) { var bRes = false; try { base.UpdateDto(userRepository, oUser); bRes = true; } catch { } return bRes; } #endregion #region 部門管理 public List GetDepartments(ExpressionNode expressionNode) { Expressionbool>> selector = null; if (expressionNode != null) { selector = expressionNode.ToExpressionbool>>(); } return base.GetDtoByLamada(departmentRepository, selector); } public DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept) { return base.AddDto(departmentRepository, oDept); } public bool DeleteDepartment(DTO_TB_DEPARTMENT oDept) { var bRes = false; try { base.DeleteDto(departmentRepository, oDept); bRes = true; } catch { } return bRes; } public bool DeleteDeptByLamada(ExpressionNode expressionNode) { Expressionbool>> selector = null; if (expressionNode != null) { selector = expressionNode.ToExpressionbool>>(); } var bRes = false; try { base.DeleteDto(departmentRepository, selector); bRes = true; } catch { } return bRes; } public bool UpdateDepartment(DTO_TB_DEPARTMENT oDept) { var bRes = false; try { base.UpdateDto(departmentRepository, oDept); bRes = true; } catch { } return bRes; } #endregion #region 角色管理 public List GetRoles(ExpressionNode expressionNode) { Expressionbool>> selector = null; if (expressionNode != null) { selector = expressionNode.ToExpressionbool>>(); } return base.GetDtoByLamada(roleRepository, selector); } public DTO_TB_ROLE AddRole(DTO_TB_ROLE oRole) { return base.AddDto(roleRepository, oRole); } #endregion #region 選單管理 public List GetMenus(ExpressionNode expressionNode) { Expressionbool>> selector = null; if (expressionNode != null) { selector = expressionNode.ToExpressionbool>>(); } return base.GetDtoByLamada(menuRepository, selector); } public DTO_TB_MENU AddMenu(DTO_TB_MENU oMenu) { return base.AddDto(menuRepository, oMenu); } #endregion #endregion } |
這裡要說明一點,在通過lamada表示式查詢的方法裡面為什麼不直接用Expression>這種型別,而要使用ExpressionNode這種型別的變數呢?
這是因為Expression不支援序列化,無法用於WCF資料的傳遞。ExpressionNode這個物件的使用需要新增Serialize.Linq這個dll的引用,還好有我們神奇的NuGet,讓我們再也不用去網上找一大堆的dll了。
我們公用的增刪改查封裝到了BaseService這個父類裡面。
1.3 BaseService程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
public class BaseService { #region Fields private bool bInitAutoMapper = false; #endregion #region Construct public BaseService() { //註冊MEF Regisgter.regisgter().ComposeParts(this); } #endregion #region 查詢 /// /// 通用單表查詢方法 /// /// DTOmodel /// 領域模型 /// 需要傳過來的倉儲介面物件 /// 前端傳過來的lamada表示式 /// public List GetDtoByLamada(IRepository oRepository, Expressionbool>> selector = null) where DomainModel : AggregateRoot where DtoModel : Dto_BaseModel { InitAutoMapper(); if (selector == null) { var lstDomainModel = oRepository.Entities.ToList(); return Mapper.Map, List>(lstDomainModel); } //得到從Web傳過來和DTOModel相關的lamaba表示式的委託 Funcbool> match = selector.Compile(); //建立對映Expression的委託 Func mapper = AutoMapper.QueryableExtensions.Extensions.CreateMapExpression(Mapper.Engine).Compile(); //得到領域Model相關的lamada Expressionbool>> lamada = ef_t => match(mapper(ef_t)); List list = oRepository.Find(lamada).ToList(); return Mapper.Map, List>(list); } #endregion #region 新增 public DtoModel AddDto(IRepository oRepository, DtoModel oDtoModel) where DomainModel : AggregateRoot where DtoModel : Dto_BaseModel { InitAutoMapper(); var oDomain = Mapper.Map(oDtoModel); oRepository.Insert(oDomain); return Mapper.Map(oDomain); } #endregion #region 刪除 public int DeleteDto(IRepository oRepository, DtoModel oDtoModel) where DomainModel : AggregateRoot where DtoModel : Dto_BaseModel { InitAutoMapper(); var oDomain = Mapper.Map(oDtoModel); return oRepository.Delete(oDomain); } public int DeleteDto(IRepository oRepository, Expressionbool>> selector = null) where DomainModel : AggregateRoot where DtoModel : Dto_BaseModel { InitAutoMapper(); if (selector == null) { return 0; } //得到從Web傳過來和DTOModel相關的lamaba表示式的委託 Funcbool> match = selector.Compile(); //建立對映Expression的委託 Func mapper = AutoMapper.QueryableExtensions.Extensions.CreateMapExpression(Mapper.Engine).Compile(); //得到領域Model相關的lamada Expressionbool>> lamada = ef_t => match(mapper(ef_t)); return oRepository.Delete(lamada); } #endregion #region 更新 public void UpdateDto(IRepository oRepository, DtoModel oDtoModel) where DomainModel : AggregateRoot where DtoModel : Dto_BaseModel { InitAutoMapper(); var oDomain = Mapper.Map(oDtoModel); oRepository.Update(oDomain); } #endregion #region Private private void InitAutoMapper() { var oType = Mapper.FindTypeMapFor(); if (oType==null) { Mapper.CreateMap(); Mapper.CreateMap(); } } #endregion } |
這個父類主要做了兩件事:一是MEF的初始化;二是通用增刪改查的實現。所有dto物件和領域model的對映都在這裡統一管理。
2、UI層程式碼
UI層裡面,為了更好分離程式碼,我們引入了介面程式設計的機制,引入了ESTM.Web.IBLL和ESTM.Web.BLL兩個專案,如圖:
為什麼要有這麼一個介面層?之前 MEF實現設計上的“鬆耦合”(終結篇:面向介面程式設計)這篇已經做過介紹,對面向介面程式設計不瞭解的朋友可以看看。
2.1 ESTM.Web.IBLL程式碼
這個dll主要定義介面規則。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public interface IPowerManager { List GetUsers(Expressionbool>> selector = null); DTO_TB_USERS AddUser(DTO_TB_USERS oUser); bool DeleteUser(DTO_TB_USERS oUser); bool UpdateUser(DTO_TB_USERS oUser); bool DeleteUser(Expressionbool>> selector = null); List GetDepartments(Expressionbool>> selector = null); DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept); bool DeleteDepartment(DTO_TB_DEPARTMENT oDept); bool DeleteDepartment(Expressionbool>> selector = null); bool UpdateDepartment(DTO_TB_DEPARTMENT oDept); List GetRoles(Expressionbool>> selector = null); List GetMenus(Expressionbool>> selector = null); } |
2.2 ESTM.Web.BLL程式碼
這個dll用於實現ESTM.Web.IBLL裡面的介面方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
[Export(typeof(IPowerManager))] public class PowerManager : IPowerManager { #region Fields //建立WCF服務連線物件 private ServiceReference_PowerManager.PowerManageWCFServiceClient oService = CreatePowerManagerService.GetInstance(); #endregion #region 介面實現 public List GetUsers(Expressionbool>> selector = null) { return oService.GetUsers(GetExpressionNode(selector)); } public List GetDepartments(Expressionbool>> selector = null) { return oService.GetDepartments(GetExpressionNode(selector)); } public List GetRoles(Expressionbool>> selector = null) { return oService.GetRoles(GetExpressionNode(selector)); } public List GetMenus(Expressionbool>> selector = null) { return oService.GetMenus(GetExpressionNode(selector)); } #endregion #region Privates //將lamada表示式轉換為可用於WCF傳遞的ExpressionNode型別 private ExpressionNode GetExpressionNode(Expressionbool>> selector) { if (selector == null) { return null; } ExpressionConverter expressionConverter = new ExpressionConverter(); ExpressionNode expressionNode = expressionConverter.Convert(selector); return expressionNode; } #endregion public DTO_TB_USERS AddUser(DTO_TB_USERS oUser) { return oService.AddUser(oUser); } public bool DeleteUser(DTO_TB_USERS oUser) { return oService.DeleteUser(oUser); } public bool DeleteUser(Expressionbool>> selector = null) { if (selector == null) { return false; } ExpressionConverter expressionConverter = new ExpressionConverter(); ExpressionNode expressionNode = expressionConverter.Convert(selector); return oService.DeleteUserByLamada(expressionNode); } public bool UpdateUser(DTO_TB_USERS oUser) { return oService.UpdateUser(oUser); } public DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept) { return oService.AddDepartment(oDept); } public bool DeleteDepartment(DTO_TB_DEPARTMENT oDept) { return oService.DeleteDepartment(oDept); } public bool UpdateDepartment(DTO_TB_DEPARTMENT oDept) { return oService.UpdateDepartment(oDept); } public bool DeleteDepartment(Expressionbool>> selector = null) { if (selector == null) { return false; } ExpressionConverter expressionConverter = new ExpressionConverter(); ExpressionNode expressionNode = expressionConverter.Convert(selector); return oService.DeleteDeptByLamada(expressionNode); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class CreatePowerManagerService { private static ServiceReference_PowerManager.PowerManageWCFServiceClient oPowerManagerClient = null; private static object obj = new object(); public static ServiceReference_PowerManager.PowerManageWCFServiceClient GetInstance() { lock (obj) { if (oPowerManagerClient == null) { oPowerManagerClient = new ServiceReference_PowerManager.PowerManageWCFServiceClient(); } } return oPowerManagerClient; } } |
由於是採用的新增服務引用的方式引用的WCF服務,所以在這一層需要新增WCF服務的引用。在實現這部分程式碼的時候博主遇到過一個問題,在此和朋友們分享一下。由於在WCF服務的設計裡面用到了DTO物件,而在ESTM.Web.BLL這個專案裡面也要用到DTO,但是新增WCF服務引用的時候預設的是WCF服務裡面的DTO,而不是ESTM.Common.DtoModel這個專案的DTO物件,這樣就有問題了,每次如果我們需要改動下dto的內容,那麼我們就需要更新下服務引用。還好,微軟給我們選擇的機制,我們來看圖
這樣就能解決上面的問題了。
2.3 ESTM.Web程式碼
按照面向介面的機制,ESTM.Web專案是不需要新增ESTM.Web.BLL這個實現層專案引用的,通過MEF動態匯入ESTM.Web.BLL裡面的物件。我們來看程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
public class PowerManagerController : BaseController { [Import] private IPowerManager PowerManager { set; get; } #region Views // GET: PowerManager public ActionResult User() { return View(); } public ActionResult Role() { return View(); } public ActionResult Menu() { return View(); } public ActionResult Department() { return View(); } #endregion #region 部門管理 public JsonResult GetDepartments(int limit, int offset, string departmentname, string statu) { //得到lamada表示式 var oLamadaExtention = new LamadaExtention(); if (!string.IsNullOrEmpty(departmentname)) { oLamadaExtention.GetExpression("DEPARTMENT_NAME", departmentname, ExpressionType.Contains); } if (!string.IsNullOrEmpty(statu)) { oLamadaExtention.GetExpression("STATUS", statu, ExpressionType.Contains); } var lamada = oLamadaExtention.GetLambda(); var lstRes = PowerManager.GetDepartments(lamada); return Json(new { rows = lstRes.Skip(offset).Take(limit).ToList(), total = lstRes.Count }, JsonRequestBehavior.AllowGet); } public object GetDepartmentEdit(string strPostData) { var oDepartment = Newtonsoft.Json.JsonConvert.DeserializeObject(strPostData); if (string.IsNullOrEmpty(oDepartment.DEPARTMENT_ID)) { oDepartment.DEPARTMENT_ID = Guid.NewGuid().ToString(); oDepartment = PowerManager.AddDepartment(oDepartment); } else { PowerManager.UpdateDepartment(oDepartment); } return oDepartment; } public object DeleteDept(string strID) { PowerManager.DeleteDepartment(x=>x.DEPARTMENT_ID == strID); return new object(); } #endregion #region 選單管理 public JsonResult GetMenus(int limit, int offset, string menuname, string menuurl) { var oLamadaExtention = new LamadaExtention(); if (!string.IsNullOrEmpty(menuname)) { oLamadaExtention.GetExpression("MENU_NAME", menuname, ExpressionType.Contains); } if (!string.IsNullOrEmpty(menuurl)) { oLamadaExtention.GetExpression("MENU_URL", menuurl, ExpressionType.Contains); } var lamada = oLamadaExtention.GetLambda(); var lstRes = PowerManager.GetMenus(lamada).ToList(); return Json(new { rows = lstRes.Skip(offset).Take(limit).ToList(), total = lstRes.Count }, JsonRequestBehavior.AllowGet); } public object GetMenuEdit(string strPostData) { var oMenu = Newtonsoft.Json.JsonConvert.DeserializeObject(strPostData); if (string.IsNullOrEmpty(oMenu.MENU_ID)) { //oMenu = MenuManager.Add(oMenu); } else { //MenuManager.Update(oMenu); } return oMenu; } public object DeleteMenu(string strID) { //MenuManager.Delete(strID); return new object(); } public object GetParentMenu() { var lstMenu = PowerManager.GetMenus(x => x.MENU_LEVEL == "1"); //var lstRes = RoleManager.Find().ToList(); //var oRes = new PageRowData(); //oRes.rows = lstRes.Skip(offset).Take(limit).ToList(); //oRes.total = lstRes.Count; return lstMenu; ; } public object GetChildrenMenu(string strParentID) { var lstMenu = PowerManager.GetMenus(x => x.MENU_LEVEL == "2" & x.PARENT_ID == strParentID).ToList(); //var lstRes = RoleManager.Find().ToList(); //var oRes = new PageRowData(); //oRes.rows = lstRes.Skip(offset).Take(limit).ToList(); //oRes.total = lstRes.Count; return lstMenu; ; } #endregion #region 許可權管理 public JsonResult GetRole(int limit, int offset, string rolename, string desc) { var oLamadaExtention = new LamadaExtention(); if (!string.IsNullOrEmpty(rolename)) { oLamadaExtention.GetExpression("ROLE_NAME", rolename, ExpressionType.Contains); } if (!string.IsNullOrEmpty(desc)) { oLamadaExtention.GetExpression("DESCRIPTION", desc, ExpressionType.Contains); } var lamada = oLamadaExtention.GetLambda(); var lstRes = PowerManager.GetRoles(lamada).ToList(); return Json(new { rows = lstRes.Skip(offset).Take(limit).ToList(), total = lstRes.Count }, JsonRequestBehavior.AllowGet); } #endregion #region 使用者管理 public JsonResult GetUsers(int limit, int offset, string username, string fullname) { var oLamadaExtention = new LamadaExtention(); if (!string.IsNullOrEmpty(username)) { oLamadaExtention.GetExpression("USER_NAME", username, ExpressionType.Contains); } if (!string.IsNullOrEmpty(fullname)) { oLamadaExtention.GetExpression("FULLNAME", fullname, ExpressionType.Contains); } var lamada = oLamadaExtention.GetLambda(); var lstRes = PowerManager.GetUsers(lamada).ToList(); return Json(new { rows = lstRes.Skip(offset).Take(limit).ToList(), total = lstRes.Count }, JsonRequestBehavior.AllowGet); } public object GetUserEdit(string strPostData) { var oUser = Newtonsoft.Json.JsonConvert.DeserializeObject(strPostData); if (string.IsNullOrEmpty(oUser.USER_ID)) { oUser.USER_ID = Guid.NewGuid().ToString(); oUser = PowerManager.AddUser(oUser); } else { PowerManager.UpdateUser(oUser); } return oUser; } public object DeleteUser(string strID) { PowerManager.DeleteUser(x => x.USER_ID == strID); return new object(); } #endregion } |
View頁面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> @Styles.Render("~/Content/css") @Styles.Render("~/Content/table-css") @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @Scripts.Render("~/bundles/bootstrap-table") @RenderSection("Scripts", false) </head> <body> @RenderBody() </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
@{ ViewBag.Title = "部門管理"; Layout = "~/Views/Shared/_Layout.cshtml"; } @Scripts.Render("~/bundles/PowerManage/DepartmentManage") <div class="panel-body" style="padding-bottom:0px;"> <div class="panel panel-default"> <div class="panel-heading">查詢條件</div> <div class="panel-body"> <div class="row"> <div class="col-md-4"> <label for="txt_search_departmentname" class="col-sm-4 control-label" style="margin-top:6px;">部門名稱</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_departmentname"> </span> </div> <div class="col-md-4"> <label for="txt_search_statu" class="col-sm-3 control-label" style="margin-top:6px;">狀態</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_statu"> </span> </div> <div class="col-md-4"> <button type="button" id="btn_query" class="btn btn-primary">查詢</button> </div> </div> </div> </div> </div> <div id="toolbar" class="btn-group"> <button id="btn_add" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增 </button> <button id="btn_edit" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>修改 </button> <button id="btn_delete" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除 </button> </div> <table id="tb_departments"></table> <form> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">新增</h4> </div> <div class="modal-body"> <div class="form-group"> <label for="txt_departmentname">部門名稱</label> <input type="text" name="txt_departmentname" class="form-control" id="txt_departmentname" placeholder="部門名稱"> </div> <div class="form-group"> <label for="txt_parentdepartment">上級部門</label> <input type="text" name="txt_parentdepartment" class="form-control" id="txt_parentdepartment" placeholder="上級部門"> </div> <div class="form-group"> <label for="txt_departmentlevel">部門級別</label> <input type="text" name="txt_departmentlevel" class="form-control" id="txt_departmentlevel" placeholder="部門級別"> </div> <div class="form-group"> <label for="txt_statu">狀態</label> <input type="text" name="txt_statu" class="form-control" id="txt_statu" placeholder="狀態"> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>關閉</button> <button type="button" id="btn_submit" class="btn btn-primary" data-dismiss="modal"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>儲存</button> </div> </div> </div> </div> </form> |
JS程式碼我們來看一個頁面就好了,其他頁面類似:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
$(function () { $('#tb_departments').bootstrapTable({ url: '/PowerManager/GetDepartments', method: 'post', toolbar: '#toolbar', pagination: true, queryParams: queryParams, queryParamsType: "limit", //ajaxOptions: { departmentname: "", statu: "" }, sidePagination: "server", pageSize: 5, pageList: [5, 25, 50, 100], search: true, strictSearch: true, showColumns: true, showRefresh: true, minimumCountColumns: 2, clickToSelect: true, columns: [{ checkbox: true }, { field: 'DEPARTMENT_NAME', title: '部門名稱' }, { field: 'PARENT_ID', title: '上級部門' }, { field: 'DEPARTMENT_LEVEL', title: '部門級別' }, { field: 'STATUS', title: '狀態' }, ], onLoadSuccess: function (data) { var odata = data; } }); var oButtonInit = new ButtonInit(); oButtonInit.Init(); }); function queryParams(params) { //配置引數 var temp = { //這裡的鍵的名字和控制器的變數名必須一直,這邊改動,控制器也需要改成一樣的 limit: params.limit, //頁面大小 offset: params.offset, //頁碼 departmentname: $("#txt_search_departmentname").val(), statu: $("#txt_search_statu").val() }; return temp; } var ButtonInit = function () { var oInit = new Object(); var postdata = {}; oInit.Init = function () { $("#btn_add").click(function () { $("#myModalLabel").text("新增"); $("#myModal").find(".form-control").val(""); $('#myModal').modal() postdata.DEPARTMENT_ID = ""; }); $("#btn_edit").click(function () { var arrselections = $("#tb_departments").bootstrapTable('getSelections'); if (arrselections.length > 1) { //alert("只能選擇一行進行編輯"); $("#btn_alert").alert(); return; } if (arrselections.length <= 0) { //alert("請先選擇需要編輯的行"); $("#btn_alert").alert() return; } $("#myModalLabel").text("編輯"); $("#txt_departmentname").val(arrselections[0].DEPARTMENT_NAME); $("#txt_parentdepartment").val(arrselections[0].PARENT_ID); $("#txt_departmentlevel").val(arrselections[0].DEPARTMENT_LEVEL); $("#txt_statu").val(arrselections[0].STATUS); postdata.DEPARTMENT_ID = arrselections[0].DEPARTMENT_ID; $('#myModal').modal(); }); $("#btn_delete").click(function () { var arrselections = $("#tb_departments").bootstrapTable('getSelections'); if (arrselections.length <= 0) { //alert("請先選擇需要編輯的行"); $("#btn_alert").alert() return; } if (!confirm("確定要刪除選定的資料嗎?")) { return; } $.ajax({ type: "post", url: "/PowerManager/DeleteDept", data: { strID: arrselections[0].DEPARTMENT_ID }, success: function (data, status) { if (status == "success") { alert("提交資料成功"); $("#tb_departments").bootstrapTable('refresh'); } }, error: function () { alert("error"); }, complete: function () { //alert("complete"); } }); }); $("#btn_submit").click(function () { postdata.DEPARTMENT_NAME = $("#txt_departmentname").val(); postdata.PARENT_ID = $("#txt_parentdepartment").val(); postdata.DEPARTMENT_LEVEL = $("#txt_departmentlevel").val(); postdata.STATUS = $("#txt_statu").val(); $.ajax({ type: "post", url: "/PowerManager/GetDepartmentEdit", data: { strPostData: JSON.stringify(postdata) }, success: function (data, status) { if (status == "success") { alert("提交資料成功"); $("#tb_departments").bootstrapTable('refresh'); } }, error: function () { //alert("error"); }, complete: function () { //alert("complete"); } }); }); $("#btn_query").click(function () { $("#tb_departments").bootstrapTable('refresh'); }); }; return oInit; }; |
效果圖:
在做頁面資料更新的時候,博主又遇到一個問題:ObjectStateManager 中已存在具有同一鍵的物件。ObjectStateManager 無法跟蹤具有相同鍵的多個物件。在此還是記錄下解決方案:
在倉儲的公共實現類中將
1 2 3 4 |
public virtual IQueryable Entities { get { return UnitOfWork.context.Set(); } } |
改成
1 2 3 4 |
public virtual IQueryable Entities { get { return UnitOfWork.context.Set().AsNoTracking() as IQueryable; } } |
就可以了。
至此,從領域模型到Web前端的程式碼基本完成,可能很多程式碼並未完善,比如異常處理、資料驗證等。
DDD領域驅動設計初探系列文章: