2018年01月10日 21:53
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

你还在用webforms拖拉控件,你还在用拖拉Ajax Control Toolkit,甚或DeveloperExpress,你Out了,快快跟我学习MVC4。

本节本人主要让那些觉得MVC比较难学的人明白,只要你想到了,就一般能做到。光有思想也不行,技术上一定要达到才行,那我问你个问题,Excel导入的时候,你怎么判断数据类型和长度?慢慢想吧!看看思想重要,还是技术重要。

首先我想上一张图,如下,还是调动一下胃口,因为无图无真相,谁看你写的博客

081434926.png

082103934.png

 看见了吧,一个纯手工打造的,没有Jquery EasyUI,没有Ajax,普通的一个界面,就这一个普通的界面,所涉及的内容可不少呢。我们先看看界面代码

@using MVCRestServiceDemo.Models.Response;  
@using MVCRestServiceDemo.Models;  
@model DataResponse<person_info>;  
<script type="text/javascript"> 
    jQuery(document).ready(function () {  
        setRowBackColor();  
        $("#btnQuery").click(function () { /*查询*/  
            var pageIndex = 1;  
            var pageSize = 12;  
            var no = $("#txtNo").val();  
            var name = $("#txtName").val();  
            var sex = $("#ddlSex").val();  
            var condition = pageIndex + "_" + pageSize + "_" + no + "|" + name + "|" + sex;  
            window.location.href = "/Home/GetArchiveInfoByCondition/" + condition;  
        });  
        $("#btnDelete").click(function () {  /*批量删除*/  
            var checkedCount = $("#tabArchiveInfo input[type='checkbox'][name!='chk_all'][checked]").length;  
            if (checkedCount == 0) {  
                alert("请选择要删除的数据!");  
                return;  
            }  
            $("#archiveInfoForm").submit(); /*提交Form*/  
        });  
    });  
    function checkall() {   /*全选*/  
        if ($("#chkall").attr("checked")) {  
            $(".mytable :checkbox").attr("checked", true);  
        }  
        else {  
            $(".mytable :checkbox").attr("checked", false);  
        }  
    }  
    function setRowBackColor() /*隔行变色*/ {  
        var t = document.getElementById("tabArchiveInfo").getElementsByTagName("tr");  
        for (var i = 0; i < t.length; i++) {  
            t[i].style.backgroundColor = (t[i].sectionRowIndex % 2 == 0) ? "#b7b3b3" : "#fff";  
        }  
    }  
    function setCheck(id) /*点击行选中或取消选中行首复选框*/ {  
        $("#chk_" + id).attr("checked", !$("#chk_" + id).attr("checked"));  
    }  
</script> 
<section class="features"> 
    @using (Html.BeginForm("Delete", "Home", FormMethod.Post, new { id = "archiveInfoForm" }))  
    {  
        <table style="width: 96%; margin-bottom: 3px"> 
            <tr> 
                <td align="right">档案编号: </td> 
                <td align="left"> 
                    @Html.TextBox("no", (ViewBag.No as string), new { id = "txtNo" })  
                </td> 
                <td align="right">姓名: </td> 
                <td align="left"> 
                    @Html.TextBox("name", (ViewBag.Name as string), new { id = "txtName" })  
                </td> 
                <td align="right">性别: </td> 
                <td align="left"> 
                    @Html.DropDownList("sex", (TempData["selectList"] as SelectList), new { id = "ddlSex" })  
                </td> 
                <td aling="center"> 
                    <input id="btnQuery" type="button" value="查询" style="width: 80px" /> 
                </td> 
            </tr> 
        </table> 
        <table class="mytable" id="tabArchiveInfo"> 
            <tr> 
                <th> 
                    <center> 
                    @Html.CheckBox("chk_all", new { id = "chkall", onclick = "checkall()" })  
                </center> 
                </th> 
                <th> 
                    <center>档案编号</center> 
                </th> 
                <th> 
                    <center>姓名</center> 
                </th> 
                <th> 
                    <center>性别</center> 
                </th> 
                <th> 
                    <center>身份证号</center> 
                </th> 
                <th> 
                    <center>出生日期</center> 
                </th> 
                <th> 
                    <center>毕业院校</center> 
                </th> 
                <th> 
                    <center>学历</center> 
                </th> 
                <th> 
                    <center>专业</center> 
                </th> 
                <th> 
                    <center>操作</center> 
                </th> 
            </tr> 
            @foreach (var personInfo in Model.DataList)  
            {  
                <tr onclick="setCheck('@personInfo.id')"> 
                    <td style="text-align: center;"> 
                        @Html.CheckBox(string.Concat("chk_", personInfo.id), false, new { id = string.Concat("chk_", personInfo.id), onclick = "setCheck('" + personInfo.id + "')" })  
                        @Html.Hidden(string.Concat("hfd_", personInfo.id), personInfo.id)  
                    </td> 
                    <td> 
                        @personInfo.no  
                    </td> 
                    <td> 
                        @personInfo.name  
                    </td> 
                    <td> 
                        @(personInfo.sex == "1" ? "男" : "女")  
                    </td> 
                    <td> 
                        @personInfo.id_card  
                    </td> 
                    <td> 
                        @personInfo.birth  
                    </td> 
                    <td> 
                        @personInfo.graduate_school  
                    </td> 
                    <td> 
                        @personInfo.education_level  
                    </td> 
                    <td> 
                        @personInfo.professional  
                    </td> 
                    <td> 
                        <button type="submit" style="width: 60px; margin-right: 3px">修改</button> 
                        <button type="submit" style="width: 60px">删除</button> 
                    </td> 
                </tr> 
            }  
        </table> 
        <div class="divpager"> 
            共有 <font color="red" id="ft">@Model.TotalCount</font>条记录 当前是第 <font color="red">@Model.PageIndex</font> 
            页 共<font color="red">@Model.TotalPages</font>页&nbsp;&nbsp;&nbsp;&nbsp;  
            @if (Model.HasPreviousPage)  
            {  
                @Html.ActionLink("首页", "GetArchiveInfoByCondition", new { id = string.Join("_", "1", Model.PageSize, ViewBag.Conition) })<label>&nbsp;  
                </label> 
                @Html.ActionLink("上一页", "GetArchiveInfoByCondition", new { id = string.Join("_", Model.PageIndex - 1, Model.PageSize, ViewBag.Conition) })<label>&nbsp;  
                </label>   
            }  
            else  
            {  
                <a>首页&nbsp;</a>   
                <a>上一页&nbsp;</a> 
            }  
            @if (Model.HasNextPage)  
            {  
                @Html.ActionLink("下一页", "GetArchiveInfoByCondition", new { id = string.Join("_", Model.PageIndex + 1, Model.PageSize, ViewBag.Conition) })<label>&nbsp;  
                </label> 
                @Html.ActionLink("末页", "GetArchiveInfoByCondition", new { id = string.Join("_", Model.TotalPages, Model.PageSize, ViewBag.Conition) })  
            }  
            else  
            {  
                <a>下一页&nbsp;</a>   
                <a>末页&nbsp;</a> 
            }  
        </div> 
        <div style="width: 96%; margin-top: 5px" align="right"> 
            <button type="button" style="width: 80px;">增加</button> 
            <button type="button" style="width: 80px" id="btnDelete">删除</button> 
        </div> 
    }  
</section>

通过界面代码,我们可以知道,我这个界面实现了界面上的隔行变色,全选/非全选,删除,查询(增加和修改功能将在下一节使用Ajax的时候介绍)功能。首先我们看第一段js。jQuery(document).ready这个函数里面实现的是隔行变色,查询,删除功能。我们先来看这个查询功能,设置window.location.href来实现页面刷新,达到查询效果。这个很容易理解,我们来看看查询代码

public ViewResult GetArchiveInfoByCondition(string id)  
        {  
            string[] pageValues = id.Split("_".ToCharArray());  
            int pageIndex = int.Parse(pageValues.ElementAt(0));  
            int pageSize = int.Parse(pageValues.ElementAt(1));  
            string[] searchValues = pageValues[2].Split("|".ToCharArray());  
            string no = searchValues.ElementAt(0) ?? string.Empty;  
            string name = searchValues.ElementAt(1) ?? string.Empty;  
            string sex = searchValues.ElementAt(2) ?? string.Empty;  
            PersonRequest request = new PersonRequest()  
            {  
                No = no.Trim(),  
                Name = name.Trim(),  
                Sex = sex.Trim(),  
                PageSize = pageSize,  
                PageIndex = pageIndex  
            };  
            ViewBag.No = request.No;  
            ViewBag.Name = request.Name;  
            ViewBag.Conition = string.Join("|", no.Trim(), name.Trim(), sex.Trim());  
            this.GetSexList(sex);  
            string uri = baseAddress + "PersonInfo/GetByCondition";  
            DataResponse<person_info> personInfoList = dataService.GetData<DataResponse<person_info>, PersonRequest>(uri, request);  
            return View("~/Views/Home/Index.cshtml", personInfoList);  
        }

在这里我要说明的是MVC和Webforms不一样,当你刷新界面的时候,文本框和下拉的值都会被刷掉,所以在这里我们有ViewBag.No = request.No;  ViewBag.Name = request.Name;意思是再把这些值重新帮回到页面,避免值被刷的情况。ViewBag.Conition = string.Join("|", no.Trim(), name.Trim(), sex.Trim());这个则是用来分页的时候传递的,因为分页的时候也要带上查询参数。至于这个DropDownList,

private void GetSexList(string selectedValue = "")  
        {  
            string uri = baseAddress + "PersonInfo/GetSexList";  
            List<codes> codeList = dataService.GetData<List<codes>>(uri);  
            codeList.Insert(0, new codes() { data = string.Empty, display_content = "---请选择---" });  
            SelectList selectList = new SelectList(codeList, "data", "display_content", selectedValue);  
            TempData["selectList"] = selectList;  
        }

因为它在往页面返的时候就要设置选定(selectedvalue),SelectList的第四个参数。这个方法的参数selectedValue 是可选参数,4.0的新特性。所以这个无需放置在ViewBag中。我们来看看这个方法对应的WCF Restful

[OperationContract]  
        [WebInvoke(UriTemplate = "Personinfo/GetByCondition", Method = "POST" 
            , RequestFormat = WebMessageFormat.Json  
            , ResponseFormat = WebMessageFormat.Json  
            , BodyStyle = WebMessageBodyStyle.Bare)]  
        DataResponse<person_info> GetPersonInfoByCondition(PersonRequest request);
 public DataResponse<person_info> GetPersonInfoByCondition(PersonRequest request)  
        {  
            IQueryable<person_info> personInfos = misInfoEntities.person_info.Where(p =>  
                 (string.IsNullOrEmpty(request.Name) ? true : p.name.Contains(request.Name.Trim()))  
                 && (string.IsNullOrEmpty(request.No) ? true : p.no.Contains(request.No.Trim()))  
                 && (string.IsNullOrEmpty(request.Sex) ? true : p.sex.Equals(request.Sex)));  
            DataResponse<person_info> response = new DataResponse<person_info>();  
            response.TotalCount = personInfos.Count();  
            response.TotalPages = response.TotalCount % request.PageSize == 0 ? (response.TotalCount / request.PageSize) : (response.TotalCount / request.PageSize + 1);  
            response.DataList = personInfos.AsEnumerable().OrderBy(p => p.no).Skip(request.PageSize * (request.PageIndex - 1)).Take(request.PageSize).ToList();  
            response.PageIndex = request.PageIndex;  
            response.PageSize = request.PageSize;  
            return response;  
        }

在这里我们一次性把相关的数据都加载到了response 中,在这里我解释下RequestFormat = WebMessageFormat.Json这个和Response设置的一致,都是json格式,也就是请求和返回所传送的数据格式都是Json,WebMessageFormat是个枚举,另一个枚举值是Xml。还有WebMessageBodyStyle,在这里我选择Bare,选择不包裹,如果包裹,意味着传递给客户端的json格式就会找不到序列化对象,假如是个对象,那么就变为{"service方法名":{"键":"值"}}这种格式,导致客户端找不到反序列化对象。在这里我们还用到了另一个对象dataService,我们来看看

public class DataService  
    {  
        public T GetData<T, P>(string url, P parameter) where T : class, new()  
        {  
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));  
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);  
            httpWebRequest.Method = "POST";  
            httpWebRequest.ContentType = "application/json";  
            using (MemoryStream ms = new MemoryStream())  
            {  
                if (parameter != null)  
                {  
                    DataContractJsonSerializer parameterSerializer = new DataContractJsonSerializer(typeof(P));  
                    Stream requestStream = httpWebRequest.GetRequestStream();  
                    parameterSerializer.WriteObject(ms, parameter);  
                    byte[] byt = ms.ToArray();  
                    requestStream.Write(byt, 0, byt.Length);  
                }  
                HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();  
                Stream responseStream = httpWebResponse.GetResponseStream();  
                T tObj = serializer.ReadObject(responseStream) as T;  
                return tObj;  
            }  
        }  
 
        public T DealData<T, P>(string url, P parameter) where T : struct 
        {  
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));  
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);  
            httpWebRequest.Method = "POST";  
            httpWebRequest.ContentType = "application/json";  
            using (MemoryStream ms = new MemoryStream())  
            {  
                if (parameter != null)  
                {  
                    DataContractJsonSerializer parameterSerializer = new DataContractJsonSerializer(typeof(P));  
                    Stream requestStream = httpWebRequest.GetRequestStream();  
                    parameterSerializer.WriteObject(ms, parameter);  
                    byte[] byt = ms.ToArray();  
                    requestStream.Write(byt, 0, byt.Length);  
                }  
                HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();  
                Stream responseStream = httpWebResponse.GetResponseStream();  
                T tObj = (T)serializer.ReadObject(responseStream);  
                return tObj;  
            }  
        }  
 
        public T GetData<T>(string url) where T : class,new()  
        {  
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));  
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);  
            httpWebRequest.Method = "Get";  
            HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();  
            Stream responseStream = httpWebResponse.GetResponseStream();  
            T tObj = serializer.ReadObject(responseStream) as T;  
            return tObj;  
        }  
    }

三个方法,第一个主要是执行POST方式的数据获取,第二个是执行POST方式的删除,修改,第三个则是执行Get方式。第三个方式的参数都是在URI中,所以无一和二那种POST序列化传值。Get典型的应用就是

public ActionResult Index()  
        {  
            ViewBag.Message = "WelCome to lilei's Mvc Demo!";  
            this.GetSexList();  
            return RedirectToAction("GetArchiveInfo");  
        }  
 
        public ViewResult GetArchiveInfo()  
        {  
            string uri = string.Format(baseAddress + "PersonInfo/GetAll/{0}/{1}", 1, 12);  
            ViewBag.Conition = string.Join("|", string.Empty, string.Empty, string.Empty);  
            DataResponse<person_info> personInfoList = dataService.GetData<DataResponse<person_info>>(uri);  
            return View("~/Views/Home/Index.cshtml", personInfoList);  
        }

程序进来以后,先获取下拉列表数据,在跳转至GetArchiveInfo这个Action,看到了,它的URI传值是追在斜杠后面的。在这里我要说下这个TempData,这个东西在控制器只传递一次就销毁了,所以我在Index中获取的 TempData["selectList"] = selectList;再传到GetArchiveInfo是不会丢失的。我们来看看这个Get的Service

[OperationContract]  
[WebGet(UriTemplate = "PersonInfo/GetAll/{pageIndex}/{pageSize}", ResponseFormat = WebMessageFormat.Json)]  
DataResponse<person_info> GetPersonInfoList(string pageIndex,string pageSize);

采用的WebGet属性标注,在这里方法中的和URI中的参数名一定要匹配,而且get方式的参数一定要定义成string类型。OK,最后我们展望一下我们的删除,就洗洗睡了。看代码Service

[OperationContract]  
[WebInvoke(UriTemplate = "PersonInfo/Delete" 
            ,BodyStyle=WebMessageBodyStyle.Bare  
            ,RequestFormat=WebMessageFormat.Json  
            ,ResponseFormat=WebMessageFormat.Json)]  
int Delete(List<string> ids); 

public int Delete(List<string> ids)  
{  
    foreach (var id in ids)  
    {  
        person_info personInfo = misInfoEntities.person_info.Find(id);  
        if (personInfo != null)  
        {  
            misInfoEntities.person_info.Remove(personInfo);  
        }  
    }  
    return misInfoEntities.SaveChanges();  
}

OK,很简单就不解释了,我们看看控制器,这是关键

public RedirectToRouteResult Delete(FormCollection fc)  
        {  
            string[] keys = fc.AllKeys;  
            string[] chkKeys=keys.Where(k=>k.Contains("chk")&&k!="chk_all").ToArray();  
            List<string> idList = new List<string>();  
            foreach (var key in chkKeys)  
            {  
                if (fc[key].ToUpper().Contains("TRUE"))  
                {  
                    idList.Add(fc[key.Replace("chk","hfd")]);  
                }  
            }  
            string uri = baseAddress + "PersonInfo/Delete";  
            dataService.DealData<Int32, List<string>>(uri, idList);  
            this.GetSexList();  
            return RedirectToAction("GetArchiveInfo");  
        }

看到了吧,我解释一下,Form提交,表单元素被提交到FormCollection(键值对),在这里我先获取所有Key,然后筛选出checkBox,循环遍历,如果包含值TRUE,注意这里如果checkbox选中,其值是"false,true",如果未选中其值是"false"。这个是MVC所决定的,我管不了。前台$("#tabArchiveInfo input[type='checkbox'][name!='chk_all'][checked]")这个意思是在id为tabArchiveInfo 的table元素中查找checkbox name不为chk_all并且状态是选中的Checkbox。如果没看懂,下一个Jquery 中文手册。OK,今天的内容就这么多,下次实战进入我们的Microsoft Ajax阶段。如果想要源码,请加入群205217091,里面很多高手,期待你的加入。

发表评论
匿名  
用户评论
暂无评论