分享的经验和教训是:
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无师自通了。当时感觉比老婆当初告诉我生的是女儿正和我意还要高兴。呵呵...
不好意思,夜已深,就此搁笔了,后续有空再补上。