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">
                            &times;
                        </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

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。