目录
- ASP.NET MVC搭建项目后台UI框架—1、后台主框架
- ASP.NET MVC搭建项目后台UI框架—2、菜单特效
- ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开
- ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
- ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互
- ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)
- ASP.NET MVC搭建项目后台UI框架—7、统计报表
- ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中
- ASP.NET MVC搭建项目后台UI框架—9、服务器端排序
接着之前未写完的继续,本篇,我将讲解在此UI框架中和ASP.NET MVC4进行结合开发。效果如下:
这里,我将添加和修改用了两个不同的视图,当然也可以把添加和修改放到同一个视图中,但是要写一些业务逻辑代码来区分当前调用的是修改还是添加,根据添加和修改的不同,而对界面进行不同的操作。
添加控制器Customer,关于更新操作,我就不得不想吐槽一下NHibernate,他妹的,每次都要先load一次,然后再Update()一次,如果你直接save,它就把你表中有,但是界面上没有传过来的值全部更新为null了,相比之下EF就好多了。
public class CustomerController : Controller { private string message = "<script>frameElement.api.opener.hidePublishWin('{0}', '{1}','{2}'); </script>"; //消息,是否关闭弹出窗,是否停留在当前分页(0,1) #region 客户管理主页 public ActionResult Index() { return View(); } /// <summary> /// 客户列表 /// </summary> /// <param name="filter"></param> /// <returns></returns> [HttpPost] public JsonResult List(CustomerFilter filter) { filter.PageSize = int.MaxValue; var dataSource = CustomerInfo.GetByFilter(filter); List<CustomerInfo> queryData = dataSource.ToList(); var data = queryData.Select(u => new { ID = u.ID, CusCode = u.CusCode, CusName = u.CusName, BusssinessType = u.BusssinessType.GetDescription(false), Balance = u.Balance, CreditAmount = u.CreditAmount, Status = u.Status.GetDescription(false), Country = u.Country, CompanyName = u.CompanyName, Delivery = GetDeliveryList(u.ExpressCurInfoBy) }); //构造成Json的格式传递 var result = new { iTotalRecords = queryData.Count, iTotalDisplayRecords = 10, data = data }; return Json(result, JsonRequestBehavior.AllowGet); } #region 添加客户 /// <summary> /// 添加客户 /// </summary> /// <param name="id"></param> /// <returns></returns> public ActionResult AddCustomer() { ViewBag.Title = "添加客户"; return View(); } /// <summary> /// 添加客户 /// </summary> /// <param name="info"></param> /// <returns></returns> [HttpPost] public ActionResult AddCustomer(CustomerInfo info) { string msg = string.Empty; if (ModelState.IsValid) { try { info.Save(); msg = "添加客户成功。"; } catch (Exception ex) { msg = "添加客户失败!" + ex.Message; ViewBag.Msg = string.Format(message, msg, false,"0"); } ViewBag.Msg = string.Format(message, msg, true,"0"); } return View(); } #endregion #region 修改客户 /// <summary> /// 修改客户 /// </summary> /// <param name="id"></param> /// <returns></returns> public ActionResult UpdateCustomer(int id) { ViewBag.Title = "修改客户"; var result = CustomerInfo.Load(id); return View(result); } /// <summary> /// 修改客户 /// </summary> /// <param name="info"></param> /// <returns></returns> [HttpPost] public ActionResult UpdateCustomer(CustomerInfo info) { string msg = string.Empty; if (ModelState.IsValid) { try { info.Update(); msg = "修改客户成功。"; } catch (Exception ex) { msg = "修改客户失败!" + ex.Message; ViewBag.Msg = string.Format(message, msg, false,"1"); } ViewBag.Msg = string.Format(message, msg, true,"1"); } return View(); } #endregion }
添加视图Index
@{ ViewBag.Title = "客户信息"; } <link href="~/libs/DataTables-1.10.6/media/css/jquery.dataTablesNew.css" rel="stylesheet" /> <script src="~/libs/DataTables-1.10.6/media/js/jquery.dataTables.min.js"></script> <script src="~/Scripts/DataTablesExt.js"></script> <script type="text/javascript"> //弹出框 var addDG, updateDG, matchDG; var w = 424, h = 520; //宽,高 //添加记录 function showPublishWin() { addDG = new $.dialog({ id: "AddChannel", title: "添加客户", content: "url:/Customer/AddCustomer", width: w, height: h, max: false, min: false, lock: true, close: true, btnBar: false }); addDG.show(); } //修改记录 function modifyRecord(id) { updateDG = new $.dialog({ id: "UpdateCustomer", title: "修改客户", content: "url:/Customer/UpdateCustomer/" + id, width: w, height: h, max: false, min: false, lock: true, close: true, btnBar: false }); updateDG.show(); } //隐藏弹出框 function hidePublishWin(msg, result, isStay) { var icon = "success.gif"; if (result == "False") { icon = "error.gif"; } $.dialog({ title: "提示", icon: icon, titleIcon: 'lhgcore.gif', content: msg, lock: true, ok: true }); if (result != "False") { if (addDG) { addDG.close(); } if (updateDG) { updateDG.close(); } if (matchDG) { matchDG.close(); } if (isStay == 0) { reloadList(); } else { reloadListNew(); } } } function matchDelivery(id) { matchDG = new $.dialog({ id: "UpdateCustomer", title: "客户匹配", content: "url:/Customer/DeliveryMatching/" + id, width: 800, height: h, max: false, min: false, lock: true, close: true, btnBar: false }); matchDG.show(); } //刷新,但是停留在当前分页 function reloadListNew() { var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/ tables.ajax.reload(null,false); } </script> <script type="text/javascript"> $(function () { var h = $(document).height() - 258; var table = $("#table_local").dataTable({ bProcessing: true, "scrollY": h, "scrollCollapse": "true", "dom": 'ftr<"bottom"lip><"clear">', "bServerSide": false, //指定从服务器端获取数据 sServerMethod: "POST", sAjaxSource: "@Url.Action("List", "Customer")", "fnServerParams": function (aoData) { //查询条件 aoData.push( { "name": "CusCode", "value": $("#CusCode").val() }, { "name": "CusName", "value": $("#CusName").val() } ); }, columns: [{ title: "1", "visible": false, "data": "ID" }, { "data": "CusCode", title: "客户代码" }, { "data": "CusName", title: "客户名称" }, { "data": "BusssinessType", title: "业务类型", width: "100" }, { "data": "Country", title: "国家", width: "200" }, { "data": "CompanyName", title: "公司名称", width: "200" }, { "data": "Delivery", title: "收货商", width: "150" }, { "data": "Balance", title: "账户余额", width: "150" }, { "data": "CreditAmount", title: "信用额度", width: "150" }, { "data": "Status", title: "是否启用", width: "100" }, { "data": "ID", orderable: false, title: "操作", width: "140", "render": function (data, type, row, meta) { //自定义列 var re = "<div style='text-align:center'><a style='visibility:visible' οnclick='modifyRecord(" + data + ")'>修改</a> "; re = re + "<a style='visibility:visible' οnclick='matchDelivery(" + data + ")'>匹配</a></div>"; return re; } } ], paging: true,//分页 ordering: true,//是否启用排序 searching: true,//搜索 language: { "sProcessing": "处理中...", lengthMenu: '每页显示:<select class="form-control input-xsmall">' + '<option value="5">5</option>' + '<option value="10">10</option>' + '<option value="15">15</option>' + '<option value="20">20</option>' + '<option value="25">25</option>' + '<option value="30">30</option>' + '<option value="35">35</option>' + '<option value="40">40</option>',//左上角的分页大小显示。 search: '<span class="label label-success">搜索:</span>',//右上角的搜索文本,可以写html标签 paginate: {//分页的样式内容。 previous: "上一页", next: "下一页", first: "", last: "" }, zeroRecords: "暂无记录",//table tbody内容为空时,tbody的内容。 //下面三者构成了总体的左下角的内容。 info: "总共 <span class='pagesStyle'>(_PAGES_) </span>页,显示 _START_ -- _END_ ,共<span class='recordsStyle'> (_TOTAL_)</span> 条",//左下角的信息显示,大写的词为关键字。初始_MAX_ 条 infoEmpty: "0条记录",//筛选为空时左下角的显示。 infoFiltered: ""//筛选之后的左下角筛选提示, }, pagingType: "full_numbers"//分页样式的类型 }); //设置选中行样式 $('#table_local tbody').on('click', 'tr', function () { if ($(this).hasClass('selected')) { $(this).removeClass('selected'); } else { table.$('tr.selected').removeClass('selected'); $(this).addClass('selected'); } }); }); //查询 刷新 function reloadList() { var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/ tables.ajax.reload(); } </script> <div class="areabx clear"> @using (Html.BeginForm("List", null, FormMethod.Get, new { @clase = "form-inline", @role = "form" })) { <div class="areabx_header">客户信息</div> <ul class="formod mgt10"> <li><span>客户代码:</span>@Html.TextBox("CusCode", "", new { @class = "trade-time wid153" })</li> <li><span>客户名称:</span>@Html.TextBox("CusName", "", new { @class = "trade-time" })</li> <li></li> </ul> <div class="botbtbx pdb0" style="margin-bottom: -30px;"> <input type="button" value="添加客户" class="btn btn-primary" onclick="showPublishWin()" /> <input type="button" value="查询" onclick="reloadList();" class="btn btn-primary"> </div> } <div class="tob_box mgt15"> <table id="table_local" class="display" cellspacing="0" cellpadding="0" border="0" style="width: 100%"> </table> </div> </div>
添加AddCustomer视图,之前公司ASP.NET MVC的项目没有启用模型验证,界面验证代码都是自己js写的,我晕,那用ASP.NET MVC干嘛呢?使用框架就是要充分发挥框架优良的功能,尽可能高效快速的开发,并减少开发人员的代码量。
@model Core.Customer.CustomerInfo @using ProjectBase.Utils @Html.Raw(ViewBag.Msg) <div class="areabx clear"> @* <div class="areabx_header">@ViewBag.Title</div>*@ <div class="tian_xi"> @using (Html.BeginForm("AddCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" })) { <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tbody> <tr style="height: 40px;"> <td style="width: 120px; text-align: right;">客户代码:</td> <td> @Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusCode)</span></td> </tr> <tr style="height: 40px;"> <td align="right">客户名称:</td> <td> @Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusName)</span></td> </tr> <tr style="height: 40px;"> <td align="right">手机:</td> <td> @Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">电话:</td> <td> @Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">邮箱:</td> <td> @Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" })<span class="wtps">@Html.ValidationMessageFor(m => m.Email)</span></td> </tr> <tr style="height: 40px;"> <td align="right">传真:</td> <td> @Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">国家:</td> <td> @Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">地址:</td> <td> @Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">公司名称:</td> <td> @Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">业务类型:</td> <td> @Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" }) </tr> <tr style="height: 40px;"> <td align="right">是否启用:</td> <td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" }) <span class="radioMagin">否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</span></td> </tr> </tbody> </table> <input type="submit" value="确定" class="popbtn1 mg"> <input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.addDG.close();" /> } </div> </div>
添加UpdateCustomer视图
@model Core.Customer.CustomerInfo @using ProjectBase.Utils @Html.Raw(ViewBag.Msg) <div class="areabx clear"> @* <div class="areabx_header">@ViewBag.Title</div>*@ <div class="tian_xi"> @using (Html.BeginForm("UpdateCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" })) { <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tbody> <tr style="height: 40px;"> <td style="width: 120px; text-align: right;">客户代码:</td> <td> @Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode", @readOnly = "readOnly" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusCode)</span></td> @Html.HiddenFor(x => x.ID) </tr> <tr style="height: 40px;"> <td align="right">客户名称:</td> <td> @Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusName)</span></td> </tr> <tr style="height: 40px;"> <td align="right">手机:</td> <td> @Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">电话:</td> <td> @Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">邮箱:</td> <td> @Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" }) <span class="wtps">@Html.ValidationMessageFor(m => m.Email)</span></td> </tr> <tr style="height: 40px;"> <td align="right">传真:</td> <td> @Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">国家:</td> <td> @Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">地址:</td> <td> @Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">公司名称:</td> <td> @Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td> </tr> <tr style="height: 40px;"> <td align="right">业务类型:</td> <td> @Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" }) </tr> <tr style="height: 40px;"> <td align="right">是否启用:</td> <td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" }) <span class="radioMagin">否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</span></td> </tr> </tbody> </table> <input type="submit" value="确定" class="popbtn1 mg"> <input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.updateDG.close();" /> } </div> </div>
客户实体CustomerInfo
/// <summary> /// 客户信息 /// </summary> public class CustomerInfo //: DomainObject<CustomerInfo, int, ICustomerInfoRepository> { #region property /// <summary> /// 客户代码 /// </summary> [Required(ErrorMessage = "客户代码不能为空!")] [StringLength(30, MinimumLength = 0, ErrorMessage = "客户代码最大长度为30个字符")] public virtual string CusCode { get; set; } /// <summary> /// 客户名称 /// </summary> [Required(ErrorMessage = "客户名称不能为空!")] [StringLength(30, MinimumLength = 0, ErrorMessage = "客户名称最大长度为30个字符")] public virtual string CusName { get; set; } /// <summary> /// 客户业务类型 /// </summary> public virtual Busssiness BusssinessType { get; set; } /// <summary> /// 手机 /// </summary> public virtual string Phone { get; set; } /// <summary> /// 电话 /// </summary> public virtual string Tel { get; set; } /// <summary> /// 邮箱 /// </summary> [RegularExpression(@"^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$", ErrorMessage="邮箱格式不正确!")] public virtual string Email { get; set; } /// <summary> /// 传真 /// </summary> public virtual string Fax { get; set; } /// <summary> /// 国家 /// </summary> public virtual string Country { get; set; } /// <summary> /// 地址 /// </summary> public virtual string Address { get; set; } /// <summary> /// 公司名称 /// </summary> public virtual string CompanyName { get; set; } /// <summary> /// 金额 /// </summary> public virtual decimal Balance { get; set; } /// <summary> /// 信用额度 /// </summary> public virtual decimal CreditAmount { get; set; } /// <summary> /// 状态 /// </summary> public virtual CustomerStatus Status { get; set; } /// <summary> /// 快件收货商信息 /// </summary> public virtual IList<ExpressCurInfo> ExpressCurInfoBy { get; set; } #endregion #region common method /// <summary> /// 分页获取数据 /// </summary> /// <param name="filter"></param> /// <returns></returns> public static IPageOfList<CustomerInfo> GetByFilter(CustomerFilter filter) { return Dao.GetByFilter(filter); } #endregion }
查询类CustomerFilter
public class CustomerFilter : ParameterFilter { /// <summary> /// 客户代码 /// </summary> public virtual string CusCode { get; set; } /// <summary> /// 客户名称 /// </summary> public virtual string CusName { get; set; } /// <summary> /// 生产NHQL查询语句 /// </summary> /// <returns></returns> public override string ToHql() { string hql = ""; if (!string.IsNullOrEmpty(CusCode)) { hql += " and Cus_Code =:CusCode "; } if (!string.IsNullOrEmpty(CusName)) { hql += " and Cus_Name =:CusName "; } return hql; } /// <summary> /// 构造查询参数 /// </summary> /// <returns></returns> public override Dictionary<string, object> GetParameters() { var result = new Dictionary<string, object>(); if (!string.IsNullOrEmpty(CusCode)) { result["CusCode"] = CusCode.Trim(); } if (!string.IsNullOrEmpty(CusName)) { result["CusName"] = CusName.Trim(); } return result; } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using ProjectBase.Utils.Entities; namespace ProjectBase.Data { public abstract class ParameterFilter { public ParameterFilter() { HasQueryString = false; PageSize = 10; } public string OrderBy { get;set; } public abstract string ToHql(); public override string ToString() { return ToHql(); } public abstract Dictionary<string, object> GetParameters(); public string GetOrderString() { if (OrderBy.HasValue()) return " Order By " + OrderBy; return String.Empty; } protected string GetLike(string value) { return "%" + value + "%"; } public int PageIndex { get; set; } public int PageSize { get; set; } /// <summary> /// 标识此构造器是包含全部查询语句。 /// 若为 False,则ToHql() 只需要构造条件查询,系统会自动在前面加上<code>" from " + typeof(T).Name + " a where 1=1 "</code> /// 若为 True, ToHql() 需要返回 连form在类的完整Hql语句 /// </summary> public bool HasQueryString { get; set; } protected static bool HasValue(string str) { return str.HasValue(); } public static bool HasValue<T>(System.Nullable<T> value) where T:struct { return value.HasValue; } } }
在这里,我只演示了控制器和视图的交互,至于Hhibernate和Unity等数据的操作,这里暂时不讲,因为你也可以使用其它的ORM框架和IOC框架,诸如EF、AutoFac等等。这里主要讲解jquery datatables和ASP.NET MVC的结合使用,但是这里只演示了客户端分页排序,后面我会讲服务器分页排序。我发现,网上都没有ASP.NET MVC和Datatables结合的完整的服务器分页、排序的Demo,只看到PHP的。于是我不断的尝试,皇天不负有心人,终于试验成功了,后面我会为大家讲述实现方式。