目錄
前言
最近在用EasyUI搭建框架,上周寫的一篇文章沒想到有這么多人看,呵呵,
看到好多人要我網站的地圖插件,http://www.5imvc.com/,本來是想寫的,結果本周都在忙框架的事情,明天有時間寫寫吧
(http://www.cnblogs.com/linfei721/archive/2013/06/02/3114174.html 地圖的代碼)
回到正題,在搭建框架的時候,無意發現自己的一個壞習慣,返回Json數據時會導致安全問題和性能的損耗,不知道其他人會不會有這習慣,寫出來大家討論下
問題
我在用LINQ返回數據習慣不寫Selet(s=>字段),直接返回全部數據,代碼:
var json = db.ReportInfo.Take(100);
return Json(json);
這樣的代碼看起來沒什么問題,但是仔細想想卻發現了問題,先看看json返回的數據

CostPrice 字段為成本價,這字段一般情況下是不讓所有人看的,如果是用戶表,這樣也會把密碼泄露出來,不管加密還是沒加密,這樣都不好
解決辦法1:拉姆達表達式
其實這就像我們在寫SQL一樣,select * from,都知道這個 * 會很影響性能,在MVC中這樣會讓很多敏感字段暴露出來,代碼改成:
var json = db.ReportInfo.Take(100).Select(s => new { AreaName = s.AreaName, FCustIDName = s.FCustIDName, FName = s.FName, FProductName = s.FProductName, HType = s.HType, 銷量 = s.銷量, 計划銷售量 = s.計划銷售量, RDate = s.RDate });
return Json(json);
然后在來看看兩種寫法的性能差異
沒寫select

改寫后

因為我這是測試數據,字段較少,速度這塊不是很明顯,但是大家可以看看文件大小,如果一個庫中字段很多,但是你頁面只需要其中幾個,這樣浪費了很多無用數據
解決辦法2:System.Linq.Dynamic
好吧,問題到這里應該完了,但是上面的代碼太麻煩,每次都寫 AreaName = s.AreaName .......這樣的代碼,
在網上找了下,終於發現了一個好東西 System.Linq.Dynamic,看名字大家應該知道了,就是動態Linq,這東西Nuget里有,直接去下載

安裝完后導入命名空間
using System.Linq.Dynamic;
改成代碼:
var json = db.ReportInfo.Take(100).Select("new (AreaName,FCustIDName,FName,FProductName,HType,銷量,計划銷售量,RDate)"); return Json(json);
解決辦法3:System.Linq.Dynamic + 自定義插件
其實在后台限制字段是最安全的,下面介紹個字段過多,解決性能但不安全的方法
在回到界面起,這是EasyUI中datagrid的寫法
<table id="list_data" cellspacing="0" cellpadding="0"> <thead> <tr> <th field="AreaName" sortable="true">省區</th> <th field="FName" sortable="true">商業公司</th> <th field="FProductName" sortable="true">產品名稱</th> <th field="HType" sortable="true">類型</th> <th field="銷量" sortable="true">數量</th> <th field="計划銷售量" sortable="true">計划</th> <th field="RDate" sortable="true">銷售日期</th> </tr> </thead> </table>
其實可以把這里需要的字段傳給后台,這樣我們后台就什么代碼就不用寫了,前台配置什么就返回什么json,自定義一個jQuery的插件,代碼如下:
$.fn.extend({
//獲取界面字段
fieldSelect: function (attr) {
var str = Array();
if (attr != undefined) {
//循環增加屬性值
$(this).each(function (index, e) {
var value = $(this).attr(attr);
//防止重復
if (jQuery.inArray(value, str) == -1)
str.push(value);
});
str = str.join(",");
}
return str;
}
});
這插件的作用就是把th中field屬性拼接成字符串,使用方法
var f = $("#list_data tr:eq(0)>th").fieldSelect("field");
//返回結果是AreaName,FCustIDName,FName,FProductName,HType,銷量,計划銷售量,RDate
$.post("url",{fieldSelect : f},function(data){
.....
});
后台代碼:
var json = db.ReportInfo.Take(100).Select(string.Format("new ({0})", Server.UrlDecode(Request.Form["fieldSelect"])));
return Json(json);
好了,這樣就是前台配置什么后台就返回什么json的數據,但是注意這里的參數別人是可以偽造的,所以並不安全,但是可以達到縮小傳送數據的目的
結束
我也是隨便想想,不知道大家有什么想法或我哪里想的不對的歡迎討論
