分享的經驗和教訓是:
1、jquery easy-ui ajax post 復雜的Json給后端解析,后端如果接收和解析
2、asp.net webform jquery easy-ui datagrid通用excel導出轉asp.net mvc
3、asp.net mvc 2 + jquery easy-ui搭建內部信息管理系統框架
由於本大叔超強的自學和動手能力,第一次正式玩asp.net mvc,由於mvc2不是使用Razor視圖引擎,有webform的開發經驗就不需要花很多時間去學習Razor語法,時間也很緊就選擇了MVC2. 在玩ajax get的時候玩得很爽,不想在需要前端頁面給后端Controller傳遞復雜Json時遇到get的url值超過長度的問題,那么搜索解決方案下來,需要使用Post方式來傳遞,Post簡單啊,一番調試,傻眼了Request里我上下左右翻了個遍,就是找不到如何接收前端頁面在HttpContext里如何取值。因為不是Post的是表單,而是復雜的Json字符串。看了很多文章還是不得要領啊,所以說是艱難的體驗。整整2天才搞定,唉,苦啊,同事那里我是不指望可以獲取幫助的,因為他們都是傳統webform的擁護者。
很多老碼農都以為啥技術想用就能用,稍微摸索一下就直接可以上手。其實也太自以為是了。基礎知識其實真心很重要,別看搞了那么多年c/s,轉b/s就是難,隨便能搞定,門都沒有!要不是一年前看過“[ASP.NET.MVC.2開發實戰][黃保翕]“那本書,真的不能那么順利就搞成了。
很多朋友喜歡說: no picture say g jb.或者說:我褲子都脫了,你給我看這個... 呵呵,上圖了,高s清哦!
前戲太長,立即轉入正題,艱難的ajax Post經歷:
上源碼咯(js):
//導出結果集到Excel function exportGrid() { if (getGridDataToExcelExport("StoreGrid").length == 0) { parent.$.messager.alert("系統提示", "記錄數為0,不需要導出!", "error"); return; } var entity = new Object(); entity.GridRows = getGridDataToExcelExport("StoreGrid"); entity.GridColumnOptions = getGridColumnFieldsOptions("StoreGrid"); entity.ExportFileName = $("#RDC_Name").combobox('getValue') + '倉庫收發貨訂單清單.xls'; $.ajax({ async: false, url: '/Home/SaveGridDataToExcelFile', type: 'POST', dataType: 'json', data: $.toJSON(entity), contentType: 'application/json; charset=utf-8', success: function (data) { if (data) { window.location = '/Home/StreamFileFromDB/?fileID=' + data.fileID.toString(); } } }); }
上面有截圖頁面傳遞的Json那是相當的復雜啊,而且想要實現通用,就是datagrid的行和列這些是變化的,網上找的大都是后端拿到傳遞的參數是反序列化成DTO對象的例子,但是抄了代碼發現也跟原文實現的不一致,比如:
單不說這種方式多么麻煩了,就是滿足不了我需要通用的要求。於是我跳過了這種方式,繼續找到下面的例子:
$("#create").click(function () { var contact = { UserName: "I love jQuery", Website: "http://www.google.com", Content: "Nice to meet you." }; $.ajax({ url: "/Contact", type: "POST", data: contact, dataType: "json", success: function (req) { $("#userTemplate").render(req).appendTo("#Contact"); } }); });
[HttpPost] public ActionResult Index(Contact contact) { if (ModelState.IsValid) { android.Contact.AddObject(contact); android.SaveChanges(); } var contacts = from c in android.Contact where c.IsValid == 1 select c; return Json(contacts); }
我測試下來斷點調試發現傳遞的參數contact始終是null,不得要領啊。
后來我又搜啊搜,發現一篇文章,測試下來終於拿到頁面的Json並反序列化了,“ASP.Net MCV 1.0 在Controller的Action Method中接收客戶端發送的JSON對象”,
終於知道原來前端傳過來的值是藏在HttpContext.Request.InputStream里啊,天啊,沒有基礎知識咋辦啊!還好終於明白真相了。於是改寫了JsonParamFilter為
JsonStringFilter達到了我只需要Json字符串的目的。
using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Web; using System.Web.Mvc; namespace BP_RFID_WMS.Controllers { public class JsonParamFilter : ActionFilterAttribute { ///<summary> ///類型名稱 ///</summary> public Type TargetType { get; set; } /// <summary> /// 參數 /// </summary> public string Param { get; set; } /// <summary> /// 將ActionExecutingContext上下文對象里的Request.InputStream流反序列化為DTO對象 /// 將 JSON 數據反序列化為對象 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { if ((filterContext.HttpContext.Request.ContentType ?? string.Empty).Contains("application/json")) { try { object o = new DataContractJsonSerializer(TargetType).ReadObject(filterContext.HttpContext.Request.InputStream); filterContext.ActionParameters[Param] = o; } catch (Exception ex) { Com.DataCool.DotNetExpand.LogHelper.Error(ex); } } } } } using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Runtime.Serialization.Json; namespace BP_RFID_WMS.Controllers { /// <summary> /// Request.InputStream流篩選器 /// </summary> public class JsonStringFilter : ActionFilterAttribute { /// <summary> /// 參數 /// </summary> public string Param { get; set; } /// <summary> /// 接受Request.InputStream流的POST數據Encoding為utf-8編碼的字符串 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { if ((filterContext.HttpContext.Request.ContentType ?? string.Empty).Contains("application/json")) { try { byte[] byts = new byte[filterContext.HttpContext.Request.InputStream.Length]; filterContext.HttpContext.Request.InputStream.Read(byts, 0, byts.Length); string req = System.Text.Encoding.UTF8.GetString(byts); req = filterContext.HttpContext.Server.UrlDecode(req); filterContext.ActionParameters[Param] = req; } catch (Exception ex) { Com.DataCool.DotNetExpand.LogHelper.Error(ex); } } } } }
使用的代碼:
/// <summary> /// 接受頁面easy-ui datagrid的行列數據並轉換成Excel文件存入數據庫 /// </summary> [JsonStringFilter(Param = "entity")] public JsonResult SaveGridDataToExcelFile(string entity) { if (!string.IsNullOrEmpty(entity)) { JObject jsonParams = JObject.Parse(entity); var gridRows = (JArray)jsonParams["GridRows"]; var gridOptions = (JArray)jsonParams["GridColumnOptions"]; var gridOptionList = (JArray)gridOptions; //可見的列 List<JObject> gridCols = new List<JObject>(); foreach (JObject j in gridOptionList) { if (j.ToString().IndexOf("hidden") == -1) { gridCols.Add(j); } } var fileName = jsonParams["ExportFileName"].Value<string>(); string tempFileName = HttpContext.Server.MapPath("~/") + "TemplateFiles\\" + "CommonExcelFile.xls"; FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read); var workBook = new HSSFWorkbook(fs); workBook.SetSheetName(0, "sheet1"); var sheet = workBook.GetSheetAt(0); //表頭(列),第一行 int newColIndex = 0; var titleRow = sheet.CreateRow(newColIndex); int cIndex = 0; foreach (JObject j in gridCols) { titleRow.CreateCell(cIndex).SetCellValue(j["title"].Value<String>()); int width = j["width"].Value<int>() / 6; if (width > 255) width = 250; sheet.SetColumnWidth(cIndex, width * 256); cIndex++; } //行記錄 for (int rowIndex = 0; rowIndex < gridRows.Count; rowIndex++) { newColIndex++; var row = sheet.CreateRow(newColIndex); var jsonEntity = gridRows[rowIndex] as JObject; for (int colIndex = 0; colIndex < gridCols.Count; colIndex++) { string cellValue = string.Empty; JObject colOption = (JObject)gridCols[colIndex]; string field = colOption["field"].Value<string>(); if (jsonEntity[field].ToString().Length != 0) cellValue = jsonEntity[field].Value<String>(); row.CreateCell(colIndex).SetCellValue(cellValue); } } MemoryStream newFile = new MemoryStream(); sheet.Workbook.Write(newFile); using (Reserve_DbEntities db = new Reserve_DbEntities()) { var resultFile = new AppExportFile(); resultFile.FileGuid = Guid.NewGuid(); resultFile.FileName = fileName; resultFile.FileCreateDateTime = DateTime.Now; resultFile.FileStreamByte = newFile.GetBuffer(); db.AddToAppExportFile(resultFile); db.SaveChanges(); var data = new { fileID = resultFile.FileGuid.ToString() }; return Json(data, JsonRequestBehavior.AllowGet); } } else return Json(string.Empty, JsonRequestBehavior.AllowGet); }
OK,終於成功了,還需要補充一點ajax post默認是異步的,在回調函數里寫了很多alter類似的代碼當時都沒執行這些都難到了我,后來發現Chrome的F12開發者工具真是神器啊,OK無師自通了。當時感覺比老婆當初告訴我生的是女兒正和我意還要高興。呵呵...
不好意思,夜已深,就此擱筆了,后續有空再補上。