關於T4代碼生成這塊,我之前寫過幾篇帖子,如:《Magicodes.NET框架之路——讓代碼再飛一會(ASP.NET Scaffolding)》(http://www.cnblogs.com/codelove/p/4251533.html)、《Magicodes.NET框架之路——讓Magicodes.NET幫你編寫代碼》(http://www.cnblogs.com/codelove/p/4232659.html)。ASP.NET Scaffolding雖然有些不足,但是思慮再三,考慮到時間成本,Magicodes.WeiChat中還是采用了ASP.NET Scaffolding模板來生成業務代碼。目前已經實現了創建、刪除、查看、編輯、分頁、搜索、刪除確認、批量操作、批量刪除、支持日期控件、支持多個主鍵等情形的代碼生成。
我們先來看看效果圖:
效果圖
代碼基架的定制與修改
關於ASP.NET代碼基架的知識與操作,請閱讀此處(http://www.cnblogs.com/codelove/p/4251533.html),這里就不多說了。
雖然ASP.NET Scaffolding Template存在一些缺陷,無法完美的實現某些代碼生成的問題,但是我們目前不需要到這個級別,因此還是勉強夠用了。
如下圖所示,我們修改了基架模板,目錄位置如下:
其中,我們需要重點關注以下兩個目錄:
MvcControllerWithContext:該目錄下的模板為添加控制器時,選擇基架項為【包含視圖的 MVC5 控制器(使用Entity Framework)】時生成控制器代碼的T4模板。
MvcView:該目錄下的模板為添加控制器時,選擇基架項為【包含視圖的 MVC5 控制器(使用Entity Framework)】時生成增刪改查視圖的代碼的T4模板。
然后,我們就開始生成之旅。
代碼生成
添加控制器,選擇代碼基架
這里選擇【包含視圖的MVC5控制器(使用 Entity Framework)】。
添加控制器
個人比較喜歡使用異步控制器操作。
生成的代碼
我們先來看看生成的列表代碼:
// GET: WeiChat_KeyWordTextContent public async Task<ActionResult> Index(string q, int pageIndex = 1, int pageSize = 10) { var queryable = db.WeiChat_KeyWordTextContents.Include(p => p.CreateUser).Include(p => p.UpdateUser).AsQueryable(); if (!string.IsNullOrWhiteSpace(q)) { //請替換為相應的搜索邏輯 queryable = queryable.Where(p => p.Text.Contains(q) || p.KeyWord.Contains(q) || p.CreateBy.Contains(q) || p.UpdateBy.Contains(q)); } var pagedList = new PagedList<WeiChat_KeyWordTextContent>( await queryable.OrderBy(p => p.Id) .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(), pageIndex, pageSize, await queryable.CountAsync()); return View(pagedList); }
代碼中默認就實現了分頁邏輯與搜索邏輯,不過搜索邏輯目前只是簡單的搜索邏輯,開發者可以根據自己的需求修改為自己的搜索邏輯。
創建、編輯、刪除的代碼這里就略過了。這里介紹下批量操作的代碼:
// POST: WeiChat_KeyWordTextContent/BatchOperation/{operation} /// <summary> /// 批量操作 /// </summary> /// <param name="operation">操作方法</param> /// <param name="ids">主鍵集合</param> /// <returns></returns> [HttpPost] [Route("WeiChat_KeyWordTextContent/BatchOperation/{operation}")] public async Task<ActionResult> BatchOperation(string operation, params Guid?[] ids) { var ajaxResponse = new AjaxResponse(); if (ids.Length > 0) { try { var models = await db.WeiChat_KeyWordTextContents.Where(p => ids.Contains(p.Id)).ToListAsync(); if (models.Count == 0) { ajaxResponse.Success = false; ajaxResponse.Message = "沒有找到匹配的項,項已被刪除或不存在!"; return Json(ajaxResponse); } switch (operation.ToUpper()) { case "DELETE": #region 刪除 { db.WeiChat_KeyWordTextContents.RemoveRange(models); await db.SaveChangesAsync(); ajaxResponse.Success = true; ajaxResponse.Message = string.Format("已成功操作{0}項!", models.Count); break; } #endregion default: break; } } catch (Exception ex) { ajaxResponse.Success = false; ajaxResponse.Message = ex.Message; } } else { ajaxResponse.Success = false; ajaxResponse.Message = "請至少選擇一項!"; } return Json(ajaxResponse); }
批量操作是很常見的一個場景,這里自動生成了批量刪除的代碼。當然,你也可以根據需要將此處修改為軟刪除。
然后視圖這塊,生成了批量操作的前端代碼:
function batchOperation(operation, comfirmMessage) { var $checkInputs = $("input[type=checkbox][name=ids]:checked"); if ($checkInputs.length == 0) { mwc.message.warn("請至少選擇一項!"); return; } function post() { var ids = new Array(); $.each($("input[type=checkbox][name=ids]:checked").serializeArray(), function (i, v) { ids.push(v.value); }); mwc.restApi.post({ url: "@Request.RequestContext.RouteData.GetRequiredString("controller")/BatchOperation/" + operation, contentType: "application/x-www-form-urlencoded", data: { ids: ids }, success: function (data) { location.reload(); } }); } if (comfirmMessage) { mwc.message.confirm("", comfirmMessage, function (isConfirmed) { isConfirmed && post(); }); } else { post(); } } $(function () { $('input[type=checkbox]').iCheck({ checkboxClass: 'icheckbox_square-green', radioClass: 'iradio_square-green', }); $("#chkCheckAll").on('ifToggled', function (e) { $("input[type=checkbox][name=ids]").iCheck(e.currentTarget.checked ? "check" : "uncheck"); }) //批量操作 $("#toolBar button[data-action],a[data-action]").on('click', function () { batchOperation($(this).data("action"), $(this).data("comfirmmessage")); }); });
對於新增、編輯視圖,生成了日歷控件的代碼,不過可以按照個人需求選擇注銷。
同時,模板也支持多主鍵代碼生成,例如前端復選框選擇代碼:
<input type="checkbox" name="ids" class="i-checks" value="@(item.BillID + " ;" + item.ItemNo)" />
操作代碼:
<li>@Html.ActionLink("編輯", "Edit", new { id = item.BillID + ";" + item.ItemNo })</li> <li>@Html.ActionLink("刪除", "Delete", new { id = item.BillID + ";" + item.ItemNo })</li>
然后,批量操作的方法參數也修改為string數組:
public async Task<ActionResult> BatchOperation(string operation, params string[] ids)
而獲取批量操作的對象也根據多個主鍵進行了篩選:
var models = await db.B_RecommendDet.Where(p => ids.Contains(p.BillID + ";" + p.ItemNo)).ToListAsync();
同樣的,增刪等操作也進行了處理:
var ids = id.Split(';'); var id0 = int.Parse(ids[0]); var id1 = int.Parse(ids[1]); B_RecommendDet b_RecommendDet = await db.B_RecommendDet.FindAsync(id0, id1);
尾聲
並不打算過多的介紹,那就到此為止吧。
- 之所以沒有沿用之前摸索出來的代碼生成方式,主要是因為個人精力有限,暫時難以花費太多精力在代碼生成這塊。
- 好的架構是根據自身業務重構出來的,適合自己的架構就是好的。
- 在代碼設計方面,本人現在更熱衷於簡單設計,輕架構,“簡單”代碼。