ASP.NET MVC4+EF4.1+WCF RESTful 实战(一)

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

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

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

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

  
  
  
  
  1. @using MVCRestServiceDemo.Models.Response;  
  2. @using MVCRestServiceDemo.Models;  
  3. @model DataResponse<person_info>;  
  4. <script type="text/javascript"> 
  5.     jQuery(document).ready(function () {  
  6.         setRowBackColor();  
  7.         $("#btnQuery").click(function () { /*查询*/  
  8.             var pageIndex = 1;  
  9.             var pageSize = 12;  
  10.             var no = $("#txtNo").val();  
  11.             var name = $("#txtName").val();  
  12.             var sex = $("#ddlSex").val();  
  13.             var condition = pageIndex + "_" + pageSize + "_" + no + "|" + name + "|" + sex;  
  14.             window.location.href = "/Home/GetArchiveInfoByCondition/" + condition;  
  15.         });  
  16.         $("#btnDelete").click(function () {  /*批量删除*/  
  17.             var checkedCount = $("#tabArchiveInfo input[type='checkbox'][name!='chk_all'][checked]").length;  
  18.             if (checkedCount == 0) {  
  19.                 alert("请选择要删除的数据!");  
  20.                 return;  
  21.             }  
  22.             $("#archiveInfoForm").submit(); /*提交Form*/  
  23.         });  
  24.     });  
  25.     function checkall() {   /*全选*/  
  26.         if ($("#chkall").attr("checked")) {  
  27.             $(".mytable :checkbox").attr("checked", true);  
  28.         }  
  29.         else {  
  30.             $(".mytable :checkbox").attr("checked", false);  
  31.         }  
  32.     }  
  33.     function setRowBackColor() /*隔行变色*/ {  
  34.         var t = document.getElementById("tabArchiveInfo").getElementsByTagName("tr");  
  35.         for (var i = 0; i < t.length; i++) {  
  36.             t[i].style.backgroundColor = (t[i].sectionRowIndex % 2 == 0) ? "#b7b3b3" : "#fff";  
  37.         }  
  38.     }  
  39.     function setCheck(id) /*点击行选中或取消选中行首复选框*/ {  
  40.         $("#chk_" + id).attr("checked", !$("#chk_" + id).attr("checked"));  
  41.     }  
  42. </script> 
  43. <section class="features"> 
  44.     @using (Html.BeginForm("Delete", "Home", FormMethod.Post, new { id = "archiveInfoForm" }))  
  45.     {  
  46.         <table style="width: 96%; margin-bottom: 3px"> 
  47.             <tr> 
  48.                 <td align="right">档案编号: </td> 
  49.                 <td align="left"> 
  50.                     @Html.TextBox("no", (ViewBag.No as string), new { id = "txtNo" })  
  51.                 </td> 
  52.                 <td align="right">姓名: </td> 
  53.                 <td align="left"> 
  54.                     @Html.TextBox("name", (ViewBag.Name as string), new { id = "txtName" })  
  55.                 </td> 
  56.                 <td align="right">性别: </td> 
  57.                 <td align="left"> 
  58.                     @Html.DropDownList("sex", (TempData["selectList"] as SelectList), new { id = "ddlSex" })  
  59.                 </td> 
  60.                 <td aling="center"> 
  61.                     <input id="btnQuery" type="button" value="查询" style="width: 80px" /> 
  62.                 </td> 
  63.             </tr> 
  64.         </table> 
  65.         <table class="mytable" id="tabArchiveInfo"> 
  66.             <tr> 
  67.                 <th> 
  68.                     <center> 
  69.                     @Html.CheckBox("chk_all", new { id = "chkall"onclick = "checkall()" })  
  70.                 </center> 
  71.                 </th> 
  72.                 <th> 
  73.                     <center>档案编号</center> 
  74.                 </th> 
  75.                 <th> 
  76.                     <center>姓名</center> 
  77.                 </th> 
  78.                 <th> 
  79.                     <center>性别</center> 
  80.                 </th> 
  81.                 <th> 
  82.                     <center>身份证号</center> 
  83.                 </th> 
  84.                 <th> 
  85.                     <center>出生日期</center> 
  86.                 </th> 
  87.                 <th> 
  88.                     <center>毕业院校</center> 
  89.                 </th> 
  90.                 <th> 
  91.                     <center>学历</center> 
  92.                 </th> 
  93.                 <th> 
  94.                     <center>专业</center> 
  95.                 </th> 
  96.                 <th> 
  97.                     <center>操作</center> 
  98.                 </th> 
  99.             </tr> 
  100.             @foreach (var personInfo in Model.DataList)  
  101.             {  
  102.                 <tr onclick="setCheck('@personInfo.id')"> 
  103.                     <td style="text-align: center;"> 
  104.                         @Html.CheckBox(string.Concat("chk_", personInfo.id), false, new { id = string.Concat("chk_", personInfo.id), onclick = "setCheck('" + personInfo.id + "')" })  
  105.                         @Html.Hidden(string.Concat("hfd_", personInfo.id), personInfo.id)  
  106.                     </td> 
  107.                     <td> 
  108.                         @personInfo.no  
  109.                     </td> 
  110.                     <td> 
  111.                         @personInfo.name  
  112.                     </td> 
  113.                     <td> 
  114.                         @(personInfo.sex == "1" ? "男" : "女")  
  115.                     </td> 
  116.                     <td> 
  117.                         @personInfo.id_card  
  118.                     </td> 
  119.                     <td> 
  120.                         @personInfo.birth  
  121.                     </td> 
  122.                     <td> 
  123.                         @personInfo.graduate_school  
  124.                     </td> 
  125.                     <td> 
  126.                         @personInfo.education_level  
  127.                     </td> 
  128.                     <td> 
  129.                         @personInfo.professional  
  130.                     </td> 
  131.                     <td> 
  132.                         <button type="submit" style="width: 60px; margin-right: 3px">修改</button> 
  133.                         <button type="submit" style="width: 60px">删除</button> 
  134.                     </td> 
  135.                 </tr> 
  136.             }  
  137.         </table> 
  138.         <div class="divpager"> 
  139.             共有 <font color="red" id="ft">@Model.TotalCount</font>条记录 当前是第 <font color="red">@Model.PageIndex</font> 
  140.             页 共<font color="red">@Model.TotalPages</font>页&nbsp;&nbsp;&nbsp;&nbsp;  
  141.             @if (Model.HasPreviousPage)  
  142.             {  
  143.                 @Html.ActionLink("首页", "GetArchiveInfoByCondition", new { id = string.Join("_", "1", Model.PageSize, ViewBag.Conition) })<label>&nbsp;  
  144.                 </label> 
  145.                 @Html.ActionLink("上一页", "GetArchiveInfoByCondition", new { id = string.Join("_", Model.PageIndex - 1, Model.PageSize, ViewBag.Conition) })<label>&nbsp;  
  146.                 </label>   
  147.             }  
  148.             else  
  149.             {  
  150.                 <a>首页&nbsp;</a>   
  151.                 <a>上一页&nbsp;</a> 
  152.             }  
  153.             @if (Model.HasNextPage)  
  154.             {  
  155.                 @Html.ActionLink("下一页", "GetArchiveInfoByCondition", new { id = string.Join("_", Model.PageIndex + 1, Model.PageSize, ViewBag.Conition) })<label>&nbsp;  
  156.                 </label> 
  157.                 @Html.ActionLink("末页", "GetArchiveInfoByCondition", new { id = string.Join("_", Model.TotalPages, Model.PageSize, ViewBag.Conition) })  
  158.             }  
  159.             else  
  160.             {  
  161.                 <a>下一页&nbsp;</a>   
  162.                 <a>末页&nbsp;</a> 
  163.             }  
  164.         </div> 
  165.         <div style="width: 96%; margin-top: 5px" align="right"> 
  166.             <button type="button" style="width: 80px;">增加</button> 
  167.             <button type="button" style="width: 80px" id="btnDelete">删除</button> 
  168.         </div> 
  169.     }  
  170. </section> 

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

  
  
  
  
  1. public ViewResult GetArchiveInfoByCondition(string id)  
  2.         {  
  3.             string[] pageValues = id.Split("_".ToCharArray());  
  4.             int pageIndex = int.Parse(pageValues.ElementAt(0));  
  5.             int pageSize = int.Parse(pageValues.ElementAt(1));  
  6.             string[] searchValues = pageValues[2].Split("|".ToCharArray());  
  7.             string no = searchValues.ElementAt(0) ?? string.Empty;  
  8.             string name = searchValues.ElementAt(1) ?? string.Empty;  
  9.             string sex = searchValues.ElementAt(2) ?? string.Empty;  
  10.             PersonRequest request = new PersonRequest()  
  11.             {  
  12.                 No = no.Trim(),  
  13.                 Name = name.Trim(),  
  14.                 Sex = sex.Trim(),  
  15.                 PageSize = pageSize,  
  16.                 PageIndex = pageIndex  
  17.             };  
  18.             ViewBag.No = request.No;  
  19.             ViewBag.Name = request.Name;  
  20.             ViewBag.Conition = string.Join("|", no.Trim(), name.Trim(), sex.Trim());  
  21.             this.GetSexList(sex);  
  22.             string uri = baseAddress + "PersonInfo/GetByCondition";  
  23.             DataResponse<person_info> personInfoList = dataService.GetData<DataResponse<person_info>, PersonRequest>(uri, request);  
  24.             return View("~/Views/Home/Index.cshtml", personInfoList);  
  25.         } 

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

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

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

  
  
  
  
  1. [OperationContract]  
  2.         [WebInvoke(UriTemplate = "Personinfo/GetByCondition", Method = "POST" 
  3.             , RequestFormat = WebMessageFormat.Json  
  4.             , ResponseFormat = WebMessageFormat.Json  
  5.             , BodyStyle = WebMessageBodyStyle.Bare)]  
  6.         DataResponse<person_info> GetPersonInfoByCondition(PersonRequest request); 
  
  
  
  
  1. /// <summary>  
  2.         /// 根据查询条件获取  
  3.         /// </summary>  
  4.         /// <param name="request"></param>  
  5.         /// <returns></returns>  
  6.         public DataResponse<person_info> GetPersonInfoByCondition(PersonRequest request)  
  7.         {  
  8.             IQueryable<person_info> personInfos = misInfoEntities.person_info.Where(p =>  
  9.                  (string.IsNullOrEmpty(request.Name) ? true : p.name.Contains(request.Name.Trim()))  
  10.                  && (string.IsNullOrEmpty(request.No) ? true : p.no.Contains(request.No.Trim()))  
  11.                  && (string.IsNullOrEmpty(request.Sex) ? true : p.sex.Equals(request.Sex)));  
  12.             DataResponse<person_info> response = new DataResponse<person_info>();  
  13.             response.TotalCount = personInfos.Count();  
  14.             response.TotalPages = response.TotalCount % request.PageSize == 0 ? (response.TotalCount / request.PageSize) : (response.TotalCount / request.PageSize + 1);  
  15.             response.DataList = personInfos.AsEnumerable().OrderBy(p => p.no).Skip(request.PageSize * (request.PageIndex - 1)).Take(request.PageSize).ToList();  
  16.             response.PageIndex = request.PageIndex;  
  17.             response.PageSize = request.PageSize;  
  18.             return response;  
  19.         } 

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

  
  
  
  
  1. public class DataService  
  2.     {  
  3.         public T GetData<T, P>(string url, P parameter) where T : classnew()  
  4.         {  
  5.             DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));  
  6.             HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);  
  7.             httpWebRequest.Method = "POST";  
  8.             httpWebRequest.ContentType = "application/json";  
  9.             using (MemoryStream ms = new MemoryStream())  
  10.             {  
  11.                 if (parameter != null)  
  12.                 {  
  13.                     DataContractJsonSerializer parameterSerializer = new DataContractJsonSerializer(typeof(P));  
  14.                     Stream requestStream = httpWebRequest.GetRequestStream();  
  15.                     parameterSerializer.WriteObject(ms, parameter);  
  16.                     byte[] byt = ms.ToArray();  
  17.                     requestStream.Write(byt, 0, byt.Length);  
  18.                 }  
  19.                 HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();  
  20.                 Stream responseStream = httpWebResponse.GetResponseStream();  
  21.                 T tObj = serializer.ReadObject(responseStream) as T;  
  22.                 return tObj;  
  23.             }  
  24.         }  
  25.  
  26.         public T DealData<T, P>(string url, P parameter) where T : struct 
  27.         {  
  28.             DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));  
  29.             HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);  
  30.             httpWebRequest.Method = "POST";  
  31.             httpWebRequest.ContentType = "application/json";  
  32.             using (MemoryStream ms = new MemoryStream())  
  33.             {  
  34.                 if (parameter != null)  
  35.                 {  
  36.                     DataContractJsonSerializer parameterSerializer = new DataContractJsonSerializer(typeof(P));  
  37.                     Stream requestStream = httpWebRequest.GetRequestStream();  
  38.                     parameterSerializer.WriteObject(ms, parameter);  
  39.                     byte[] byt = ms.ToArray();  
  40.                     requestStream.Write(byt, 0, byt.Length);  
  41.                 }  
  42.                 HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();  
  43.                 Stream responseStream = httpWebResponse.GetResponseStream();  
  44.                 T tObj = (T)serializer.ReadObject(responseStream);  
  45.                 return tObj;  
  46.             }  
  47.         }  
  48.  
  49.         public T GetData<T>(string url) where T : class,new()  
  50.         {  
  51.             DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));  
  52.             HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);  
  53.             httpWebRequest.Method = "Get";  
  54.             HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();  
  55.             Stream responseStream = httpWebResponse.GetResponseStream();  
  56.             T tObj = serializer.ReadObject(responseStream) as T;  
  57.             return tObj;  
  58.         }  
  59.     } 

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

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

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

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

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

  
  
  
  
  1. [OperationContract]  
  2.         [WebInvoke(UriTemplate = "PersonInfo/Delete" 
  3.             ,BodyStyle=WebMessageBodyStyle.Bare  
  4.             ,RequestFormat=WebMessageFormat.Json  
  5.             ,ResponseFormat=WebMessageFormat.Json)]  
  6.         int Delete(List<string> ids); 
  
  
  
  
  1. public int Delete(List<string> ids)  
  2.         {  
  3.             foreach (var id in ids)  
  4.             {  
  5.                 person_info personInfo = misInfoEntities.person_info.Find(id);  
  6.                 if (personInfo != null)  
  7.                 {  
  8.                     misInfoEntities.person_info.Remove(personInfo);  
  9.                 }  
  10.             }  
  11.             return misInfoEntities.SaveChanges();  
  12.         } 

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

  
  
  
  
  1. public RedirectToRouteResult Delete(FormCollection fc)  
  2.         {  
  3.             string[] keys = fc.AllKeys;  
  4.             string[] chkKeys=keys.Where(k=>k.Contains("chk")&&k!="chk_all").ToArray();  
  5.             List<string> idList = new List<string>();  
  6.             foreach (var key in chkKeys)  
  7.             {  
  8.                 if (fc[key].ToUpper().Contains("TRUE"))  
  9.                 {  
  10.                     idList.Add(fc[key.Replace("chk","hfd")]);  
  11.                 }  
  12.             }  
  13.             string uri = baseAddress + "PersonInfo/Delete";  
  14.             dataService.DealData<Int32, List<string>>(uri, idList);  
  15.             this.GetSexList();  
  16.             return RedirectToAction("GetArchiveInfo");  
  17.         } 

看到了吧,我解释一下,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,里面很多高手,期待你的加入。

你可能感兴趣的:(mvc,asp.net,ef,WCF)