ASP.NET MVC4+BootStrap 实战(九)
哄孩子睡觉哄到现在,要两个孩子真的是不容易。孩子不睡觉,我没办法写博客。孩子睡着了,我一写就要写到半夜2点。6点起床,6:30骑自行车去上班,呼吸着雾霾,头皮冻得僵硬。到了软件园楼底下,还要排队买胡辣汤,排队上电梯。唉,生活不易。
今天,我们要说的当然是用户信息修改,请看下图。
看到一龙了么,重庆功夫盛典和日本变装拳手战成平手,打裂了日本拳手的眉骨。OK,我们点击铅笔,弹出用户信息修改界面。那么,我们在弹出用户信息修改界面之前,先要给弹出界面的form赋值。那么这一步要怎么做,当然了,是使用angular的copy方法。怎么copy呢,当然是copy当前行的用户对象。
我们看一下弹出修改界面的js方法。
如上红框内的代码,我们调用了getSelectedUser方法,并且传入当前行的userEntity对象。看一下这个js方法是如何处理的。
$scope.modifyUser = {}; $scope.getSelectedUser = function (userEntity) { angular.copy(userEntity, $scope.modifyUser); $scope.modifyUser.UserBirthDay = new Date(parseInt($scope.modifyUser.UserBirthDay.substr(6))).format("yyyy-MM-dd"); angular.element(‘#userModifyModal‘).modal(‘show‘); };
我们定义一个modifyUser对象,然后将传递过来的对象copy到modifyUser对象。但是由于日期是json格式(/Date(1290371638000)/ ),所以需要进行转化。待对象中的数据都准备好之后,我们打开用户修改界面。
我们看一下用户修改功能在界面是如何运作的。
@using (Ajax.BeginForm("UserModify", "UserManage", null, new AjaxOptions() { HttpMethod = "Put", Confirm = "您确定要修改吗?", LoadingElementId = "div_modify_process", OnComplete = "modifyComplete", OnSuccess = "modifySuc", OnFailure = "modifyFail" }, new { @class = "form-horizontal", id = "userModify_form" })) { <div class="modal fade" id="userModifyModal" role="dialog" data-backdrop="static" data-keyboard="false" aria-labelledby="userModifyModalElement" aria-hidden="true"> <div class="modal-dialog" style="width:450px"> <div class="modal-content" style="width:450px"> <div class="modal-header modal-head"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> <h4 class="modal-title" id="userModifyModalElement"> <img src="../../Images/Base/useradd.png" class="img-panel-title" /> <label>用户信息修改</label> </h4> </div> <div class="modal-body"> <div ng-include="‘UserModifyView‘"></div> </div> <div class="modal-footer"> <button type="submit" class="btn btn-primary"> <span class="glyphicon glyphicon-check" aria-hidden="true"> <label>保存</label> </span> </button> <button type="button" ng-click="windowClose()" class="btn btn-danger"> <span class="glyphicon glyphicon-off" aria-hidden="true"> <label>关闭</label> </span> </button> </div> </div><!-- /.modal-content --> </div> </div> }
在这里需要注意的是下面的这句
<div class="modal-body"> <div ng-include="‘UserModifyView‘"></div> </div>
其实这里的ng-include是包含页面的意思。如果是静态页面,这里可能就是一个html页面。但是在asp.net mvc中,这里一定不能写cshtml或者aspx页面。因为cshtml和aspx页面是需要在服务端进行解析替换内容后才发送到客户端浏览器的。所以在这里我写的是一个controller中的action。这个action返回一个页面。
public PartialViewResult UserModifyView() { return PartialView("~/Views/UserManage/UserModify.cshtml"); }
那么我们为什么要用include呢,原因是不想将修改界面的代码直接写在查询界面上,这样通过include的方式更容易进行维护。
OK,我们看一下这个页面的代码
<div style="width:98%"> <input name="UserID" type="hidden" value="{{modifyUser.UserID}}"/> <div class=" form-group"> <div class="row"> <label class="col-md-2 control-label">姓名:</label> <div class="col-md-10 col-sm-5-pad"> <input name="UserName" type="text" maxlength="10" ng-model="modifyUser.UserName" class="form-control" data-toggle="tooltip" data-placement="bottom" title="姓名不能超过10个汉字" required> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-2 control-label"> 性别: </label> <div class="col-md-10 col-sm-5-pad"> <div class="radio-inline"> <label> <input ng-model="modifyUser.UserSex" name="UserSex" type="radio" value="1">男 </label> </div> <div class="radio-inline"> <label> <input ng-model="modifyUser.UserSex" name="UserSex" type="radio" value="0">女 </label> </div> </div> </div> </div> <div class="form-group"> <div class="row"> <label for="disabledSelect" class="col-md-2 control-label"> 生日: </label> <div class="col-md-10 col-sm-5-pad"> <input name="UserBirthDay" id="txtBirthDay" ng-model="modifyUser.UserBirthDay" type="date" class="form-control" required /> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-2 control-label"> Emai: </label> <div class="col-md-10 col-sm-5-pad"> <input name="UserEmail" type="email" maxlength="30" ng-model="modifyUser.UserEmail" class="form-control" id="txtEmail" data-toggle="tooltip" data-placement="bottom" title="请填写正确的邮箱地址,用于找回密码等" required> </div> </div> </div> <div class="form-group"> <div class="row"> <label class="col-md-2 control-label"> 电话: </label> <div class="col-md-10 col-sm-5-pad"> <input name="UserPhone" type="tel" maxlength="15" ng-model="modifyUser.UserPhone" class="form-control" id="txtTelNo" data-toggle="tooltip" data-placement="bottom" pattern="^\d{11}$" title="只能输入11位手机号码" required> </div> </div> </div> </div> <div id="div_modify_process" style="text-align:center;display:none"> <img src="~/Images/Base/loading.gif" style="width:30px;height:30px"/> <label style="color: #003399">正在处理,请稍候......</label> </div> <script type="text/javascript"> $("[data-toggle=‘tooltip‘]").tooltip(); </script>
通过include的引用,则个界面就成为了userManage界面的一部分。大家注意到,这里的表单元素绑定的都是刚才我们在弹出用户信息修改界面之前copy的对象modifyUser,这样当我们打开用户修改界面,表单上已经绑上了要修改的值,没有任何问题。由此说明,通过include引用的页面修改界面,和用户管理
界面是共享$scope的。
而且大家也注意到表单元素的name属性都是我们后台实体类中的属性。为什么这样呢,查看过asp.net mvc前端生成代码的同学都知道,其实页面最顶端声明的viewModel,只是为了方便智能提示,例如@Html.TextBoxFor(t=>t.UserID),其实这个html helper标签最终生成的html元素就是<input type=‘text‘ name=‘UserID‘>。所以我觉得页面顶端声明的viewModel类型并不会起到什么特殊的作用,因为我这个人不追求原理。所以在这里我也没在页面顶端声明什么@model xxx.xxxEntity。我只是将表单元素的name设置为后台实体的属性而已。经过验证,提交到后台是可以直接映射到实体中的。
OK,说到提交,我们看一下这个页面表单的提交,首先,上面提到这个表单的form定义如下
@using (Ajax.BeginForm("UserModify", "UserManage", null, new AjaxOptions() { HttpMethod = "Put", Confirm = "您确定要修改吗?", LoadingElementId = "div_modify_process", OnComplete = "modifyComplete", OnSuccess = "modifySuc", OnFailure = "modifyFail" }, new { @class = "form-horizontal", id = "userModify_form" })) {
这个意思是ajax方式提交到UserModify这个action,HttpMethod是Put,在提交前先弹出确认,确认后显示正在处理(LoadingElementId = "div_modify_process"),成功后弹出提示。我们看一下这几个js方法。
function modifySuc(data) { alert(data.msg); angular.element(‘#userModifyModal‘).modal(‘hide‘); //$scope.getDatabyPageIndex($scope.PageIndex); } function modifyFail(data) { alert(data); } function modifyComplete() { angular.element(‘#div_modify_process‘).hide(); }
当成功后,弹出提示信息,这里的data是mvc框架返回的回调参数,即我们后台action返回的json对象。
当ajax请求完成以后,我们需要手动隐藏正在处理(LoadingElementId = "div_modify_process")。
OK,我们来看一下后端代码
[HttpPut] public JsonResult UserModify(UserAddRequest request) { int suc = UserInfoBiz.GetInstance().ModifyUser(request); if (suc >= 0) { return GetJsonMessage("CM_003", JsonMsgType.SUCCESS); } return GetJsonMessage("CM_004"); }
提交一下试试,先弹出确认信息
点击确定之后,会出现正在处理(LoadingElementId = "div_modify_process")
提交到后台,也确实如前面所说,实体有值。
如此可见,我们只要name值和实体中的属性一致就行了。好的,我们接着看Biz层
public int ModifyUser(UserAddRequest request) { if (string.IsNullOrEmpty(request.UserID)) return -1; string xmlRequest = this.BuildUserXml(request); return UserInfoDAL.GetInstance().ModifyUser(xmlRequest); } private string BuildUserXml(UserAddRequest request) { XmlElement xmlElement = null; XmlDocument xmlDocument = new XmlDocument(); XmlNode xmlRoot = xmlDocument.CreateElement("UserInfo"); Type requestType = request.GetType(); PropertyInfo[] properties = requestType.GetProperties(); foreach (var property in properties) { xmlElement = xmlDocument.CreateElement(property.Name); xmlElement.InnerText = property.GetValue(request, null) == null ? string.Empty : property.GetValue(request, null).ToString(); xmlRoot.AppendChild(xmlElement); } return xmlRoot.OuterXml; }
看到了吧,构造一个xml格式的数据,传入DAL层。
public int ModifyUser(string xmlRequest) { try { string sqlScript = DBScriptManager.GetScript(this.GetType(), "ModifyUserInfoByID"); SqlParameter[] sqlParameters = { new SqlParameter("@UserXml",SqlDbType.Xml) }; sqlParameters[0].Value = xmlRequest; return SqlHelper.ExecuteNonQuery(ConstValues.CON_DBConnection, CommandType.Text, sqlScript, sqlParameters); } catch (Exception ex) { LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex); return -1; } }
接收的是一个xml类型的数据,其实在这里我们是直接将一个对象xml序列化之后传入sql脚本中。或者我们可以使用表值变量,直接传table进来。但是我觉得还是xml方便一些,表值变量还要在如下的地方预先定义好方能使用,比较麻烦。
最后我们看一下脚本
DECLARE @UserID VARCHAR(15) DECLARE @UserSex CHAR(1) DECLARE @UserName NVARCHAR(20) DECLARE @UserBirthDay DATETIME DECLARE @UserEmail VARCHAR(30) DECLARE @UserPhone VARCHAR(11) ;WITH UserIDList AS ( SELECT U.C.value(‘(UserID/text())[1]‘,‘VARCHAR(15)‘) AS UserID, U.C.value(‘(UserSex/text())[1]‘,‘CHAR(1)‘) AS UserSex, U.C.value(‘(UserName/text())[1]‘,‘NVARCHAR(20)‘) AS UserName, U.C.value(‘(UserBirthDay/text())[1]‘,‘DATETIME‘) AS UserBirthDay, U.C.value(‘(UserEmail/text())[1]‘,‘VARCHAR(30)‘) AS UserEmail, U.C.value(‘(UserPhone/text())[1]‘,‘VARCHAR(11)‘) AS UserPhone FROM @UserXml.nodes(N‘UserInfo‘) AS U(C) ) SELECT TOP(1) @UserID = UserID, @UserSex = UserSex, @UserName = UserName, @UserBirthDay = UserBirthDay, @UserEmail = UserEmail, @UserPhone = UserPhone FROM UserIDList UPDATE TOP(1) dbo.InformationUser SET UserName = @UserName, UserSex = @UserSex, UserBirthDay = @UserBirthDay, UserEmail = @UserEmail, UserPhone = @UserPhone WHERE UserID = @UserID
OK,最后提交完成后,弹出成功的提示。
点击确定,修改页面关闭。
本文出自 “技术创造价值” 博客,请务必保留此出处http://leelei.blog.51cto.com/856755/1611762
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。