關(guān)于html+ashx開發(fā)中幾個問題的解決方法
更新時間:2011年07月18日 00:49:49 作者:
在跟html+ashx打交道的園友們肯定會發(fā)現(xiàn),這種模式雖然優(yōu)美,但在開發(fā)中會遇到一些難處理的地方。我也不例外,下面是自己在實(shí)際開發(fā)中總結(jié)出來的幾條經(jīng)驗(yàn),希望跟大家分享,更希望得到大家的建議和更好的解決方法!
問題1:用委托字典代替switch...case。
這個問題是在處理請求時發(fā)現(xiàn)的,大家肯定也不愿意在自己的項(xiàng)目中建許多的handler來處理那么多的請求,于是就想到在一個handler里處理多個請求,ajax請求中都加一個action的參數(shù),在handler里根據(jù)這個action做相應(yīng)的處理或返回相應(yīng)的數(shù)據(jù),這里肯定沒有人用if...else來判斷action,大多數(shù)人都會想到用switch...case,一開始我也是用的switch,但漸漸地發(fā)現(xiàn),每個case不像一個代碼塊,不能為其中的變量提供一個獨(dú)立的作用域!用龍珠中孫悟空的話“真是傷腦筋”。
在網(wǎng)上搜了一下,也有不少人遇到這個問題。有個解決方法是把每個處理單獨(dú)成handler里一個方法,這樣清楚明了,但在ProcessRequest方法中要用反射調(diào)用對應(yīng)的方法!自己對這個解決辦法不太滿意,于是想到了委托,想到了字典,把反射調(diào)用方法變成在字典里索引委托。
首先在handler里聲明一個私有的靜態(tài)委托字典:
static Dictionary<string, Func<string>> hs;
然后用handler(一般處理程序的類)里靜態(tài)構(gòu)造函數(shù)初始化hs,更重要的是要在靜態(tài)構(gòu)造函數(shù)里添加處理方法:
static Handler()
{
hs = new Dictionary<string, Func<string>>();
hs.Add("add", delegate()
{
int id = int.Parse(req("id"));
string title = req("title");
return "add";
});
hs.Add("update", delegate()
{
int id = int.Parse(req("id"));
string title = req("title");
return "update";
});
}
最后就是在ProcessRequest方法里調(diào)用了:
context.Response.ContentType = "text/plain";
HttpRequest req = context.Request;
string action = req["action"].ToLower();
string result = hs[action]();
context.Response.Write(result);
這樣便避免了switch...case的變量作用域問題和反射的效率問題。關(guān)于上面用到的req()方法,我的想法是把公共的東西用靜態(tài)方法提供,如:
static string req(string key)
{
return HttpContext.Current.Request[key];
}
static string jss(object obj)
{
JavaScriptSerializer JSS = new JavaScriptSerializer();
return JSS.Serialize(obj);
}
問題2:權(quán)限問題。
你肯定不愿自己的數(shù)據(jù)在用戶沒有登陸或登陸過期后還可以繼續(xù)訪問。這里假設(shè)登陸的用戶用Session["user"]來存儲,當(dāng)然在handler里判斷一下Session["user"]是很簡單的事情,但問題是你如何讓Session["user"]為null時的用戶跳轉(zhuǎn)到指定頁(這里假設(shè)是登陸頁login.html)。哈哈,這時你會不會想到用context.Response.Redirect ("login.html")這樣一句話來解決呢!我的第一反映是這樣的,但分析一下,ajax是請求數(shù)據(jù)的,這樣做是讓ajax去請求login.html這個頁面,得到的結(jié)果應(yīng)該是login.html的源代碼才對,分析是這樣分析的,可還是不死心,還是測試了一下,結(jié)果正如分析的那樣,login.html的源代碼做為ajax請求結(jié)果返回了!
其實(shí),大家心理明白,有一個很簡單的方法,就是在Session["user"]為null時返回一個特定值,這里假設(shè)"unlogin",然后在每次ajax請求完成后判斷返回值是不是"unlogin"。
這方法很簡單,也很可靠,但很笨,很麻煩,可行性不高。于是我又想到了jquery.ajaxSuccess(),想用它來做統(tǒng)一處理,在我想到它的時候我就有點(diǎn)兒擔(dān)心,jquery會不會是先調(diào)用具體請求的回調(diào)函數(shù)然后再調(diào)用這全局的回調(diào)函數(shù)呢?我?guī)е@個疑問做了測試,結(jié)果也如預(yù)料那樣先執(zhí)行具體請求的回調(diào)再執(zhí)行全局回調(diào)!沒法辦,只好查jquery的源碼了~。在沒壓縮的jquery-1.4.2.js里找到了success()這方法,果然如此,改順序后如下:
function success() {
if ( s.global ) {
trigger( "ajaxSuccess", [xhr, s] );
}
// If a local callback was specified, fire it and pass it the data
if ( s.success && xhr.responseText!="unlogin" ) {
s.success.call( callbackContext, data, status, xhr );
}
}
執(zhí)行順序是改好了,可跳轉(zhuǎn)的代碼寫哪呢?每個頁面寫一次?不不,這不是我們寫程序的風(fēng)格,思來想去,寫到j(luò)query文件里(最下面)是一個可行的方法:
$(document).ajaxSuccess(function(event,xhr,settings){
if(xhr.responseText=="unlogin"){
window.top.location.href="/login.html";
}
})
很顯示,不是每個頁面的ajax請求都要求用戶登陸,比如login.html頁,所以判斷時要排除不用登陸的頁面:
if (HttpContext.Current.Request.UrlReferrer.ToString().ToLower().IndexOf("login.html") < 0)
{
if (HttpContext.Current.Session["user"] == null)
{
HttpContext.Current.Response.Write("unlogin");
HttpContext.Current.Response.End();
}
}
問題3:數(shù)據(jù)模板。
真是什么東西需要,什么都東西就應(yīng)運(yùn)而生!在寫這個隨筆之前正好在園里看到了個jquery.tmpl的文章!tmpl的產(chǎn)生也正是解決這個問題的!我很自知這個方法沒tmpl強(qiáng)大,但tmpl有一個問題沒有解決,其實(shí)模板有兩個主要的問題,1是如果模板存儲在js里不好編輯,2是要把模板存儲在哪里才方便設(shè)計(jì)時的視圖呢!tmpl把模板存儲在<script type="text/x-jquery-tmpl"></script>標(biāo)簽中,應(yīng)該說是解決了第一個問題,但我感覺第2個問題也是很重要的!想來想去,只能把模板直接存儲在數(shù)據(jù)的容器標(biāo)記里:
<ul id="ulList">
<li><a href="somepage.html?id={ID}">{Title}</a><br />
{Content}</li>
</ul>
把模板直接寫在目標(biāo)容器里,就像一條數(shù)據(jù)一樣,美工調(diào)樣式不是問題,程序加方法不是問題,這方法我看行!但js肯定不會直接操作這個模板吧,現(xiàn)在要做的就是把這個模板變成真的模板:
$(function() {
var ulList = $("#ulList");
ulList.data("tpl",ulList.html()).empty();
}
把模板存儲到容器的data里應(yīng)該是再適當(dāng)不過了,而且這個操作在頁面加載完馬上就做!然后把容器清空,讓位給后來加載過來的真實(shí)數(shù)據(jù)。后臺提供json數(shù)據(jù),這個很簡單:
public class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
//handler里用了上面第一個問題的解決方法
hs.Add("getNews", delegate()
{
List<News> list = new List<News>()
{
new News(){ ID=1,Title="title1",Content="Content1"},
new News(){ ID=2,Title="title2",Content="Content2"},
new News(){ ID=3,Title="title3",Content="Content3"},
};
return jss(list);
});
前臺取數(shù)據(jù)沒什么好說的,這個很基本:
$.get("Handler.ashx?n=" + Math.random(), { action: "getNews" }, function(data) {
var list = $.parseJSON(data);
var ul = $("#ulList");
var html = "";
for (var i = 0; i < list.length; i++) {
html += ul.data("tpl").format(list[i]);
}
ul.html(html);
})
在填充數(shù)據(jù)的時候用了string.format這個方法,它在我js中的string.format 隨筆里有記錄,呵呵,這個我也沒有想到,寫format的時候讓它支持json對象只是為了閱讀方便,然而用到這如此合適!到這的時候我已興奮不已了,測試結(jié)果如下:
從沒有這么認(rèn)真的寫過隨筆,三個星期就休息了這一下午,沒陪女朋友,沒睡大覺,沒找朋友喝酒,卻老老實(shí)實(shí)地把它完成了!
這個問題是在處理請求時發(fā)現(xiàn)的,大家肯定也不愿意在自己的項(xiàng)目中建許多的handler來處理那么多的請求,于是就想到在一個handler里處理多個請求,ajax請求中都加一個action的參數(shù),在handler里根據(jù)這個action做相應(yīng)的處理或返回相應(yīng)的數(shù)據(jù),這里肯定沒有人用if...else來判斷action,大多數(shù)人都會想到用switch...case,一開始我也是用的switch,但漸漸地發(fā)現(xiàn),每個case不像一個代碼塊,不能為其中的變量提供一個獨(dú)立的作用域!用龍珠中孫悟空的話“真是傷腦筋”。
在網(wǎng)上搜了一下,也有不少人遇到這個問題。有個解決方法是把每個處理單獨(dú)成handler里一個方法,這樣清楚明了,但在ProcessRequest方法中要用反射調(diào)用對應(yīng)的方法!自己對這個解決辦法不太滿意,于是想到了委托,想到了字典,把反射調(diào)用方法變成在字典里索引委托。
首先在handler里聲明一個私有的靜態(tài)委托字典:
static Dictionary<string, Func<string>> hs;
然后用handler(一般處理程序的類)里靜態(tài)構(gòu)造函數(shù)初始化hs,更重要的是要在靜態(tài)構(gòu)造函數(shù)里添加處理方法:
復(fù)制代碼 代碼如下:
static Handler()
{
hs = new Dictionary<string, Func<string>>();
hs.Add("add", delegate()
{
int id = int.Parse(req("id"));
string title = req("title");
return "add";
});
hs.Add("update", delegate()
{
int id = int.Parse(req("id"));
string title = req("title");
return "update";
});
}
最后就是在ProcessRequest方法里調(diào)用了:
復(fù)制代碼 代碼如下:
context.Response.ContentType = "text/plain";
HttpRequest req = context.Request;
string action = req["action"].ToLower();
string result = hs[action]();
context.Response.Write(result);
這樣便避免了switch...case的變量作用域問題和反射的效率問題。關(guān)于上面用到的req()方法,我的想法是把公共的東西用靜態(tài)方法提供,如:
復(fù)制代碼 代碼如下:
static string req(string key)
{
return HttpContext.Current.Request[key];
}
static string jss(object obj)
{
JavaScriptSerializer JSS = new JavaScriptSerializer();
return JSS.Serialize(obj);
}
問題2:權(quán)限問題。
你肯定不愿自己的數(shù)據(jù)在用戶沒有登陸或登陸過期后還可以繼續(xù)訪問。這里假設(shè)登陸的用戶用Session["user"]來存儲,當(dāng)然在handler里判斷一下Session["user"]是很簡單的事情,但問題是你如何讓Session["user"]為null時的用戶跳轉(zhuǎn)到指定頁(這里假設(shè)是登陸頁login.html)。哈哈,這時你會不會想到用context.Response.Redirect ("login.html")這樣一句話來解決呢!我的第一反映是這樣的,但分析一下,ajax是請求數(shù)據(jù)的,這樣做是讓ajax去請求login.html這個頁面,得到的結(jié)果應(yīng)該是login.html的源代碼才對,分析是這樣分析的,可還是不死心,還是測試了一下,結(jié)果正如分析的那樣,login.html的源代碼做為ajax請求結(jié)果返回了!
其實(shí),大家心理明白,有一個很簡單的方法,就是在Session["user"]為null時返回一個特定值,這里假設(shè)"unlogin",然后在每次ajax請求完成后判斷返回值是不是"unlogin"。
這方法很簡單,也很可靠,但很笨,很麻煩,可行性不高。于是我又想到了jquery.ajaxSuccess(),想用它來做統(tǒng)一處理,在我想到它的時候我就有點(diǎn)兒擔(dān)心,jquery會不會是先調(diào)用具體請求的回調(diào)函數(shù)然后再調(diào)用這全局的回調(diào)函數(shù)呢?我?guī)е@個疑問做了測試,結(jié)果也如預(yù)料那樣先執(zhí)行具體請求的回調(diào)再執(zhí)行全局回調(diào)!沒法辦,只好查jquery的源碼了~。在沒壓縮的jquery-1.4.2.js里找到了success()這方法,果然如此,改順序后如下:
復(fù)制代碼 代碼如下:
function success() {
if ( s.global ) {
trigger( "ajaxSuccess", [xhr, s] );
}
// If a local callback was specified, fire it and pass it the data
if ( s.success && xhr.responseText!="unlogin" ) {
s.success.call( callbackContext, data, status, xhr );
}
}
執(zhí)行順序是改好了,可跳轉(zhuǎn)的代碼寫哪呢?每個頁面寫一次?不不,這不是我們寫程序的風(fēng)格,思來想去,寫到j(luò)query文件里(最下面)是一個可行的方法:
復(fù)制代碼 代碼如下:
$(document).ajaxSuccess(function(event,xhr,settings){
if(xhr.responseText=="unlogin"){
window.top.location.href="/login.html";
}
})
很顯示,不是每個頁面的ajax請求都要求用戶登陸,比如login.html頁,所以判斷時要排除不用登陸的頁面:
復(fù)制代碼 代碼如下:
if (HttpContext.Current.Request.UrlReferrer.ToString().ToLower().IndexOf("login.html") < 0)
{
if (HttpContext.Current.Session["user"] == null)
{
HttpContext.Current.Response.Write("unlogin");
HttpContext.Current.Response.End();
}
}
問題3:數(shù)據(jù)模板。
真是什么東西需要,什么都東西就應(yīng)運(yùn)而生!在寫這個隨筆之前正好在園里看到了個jquery.tmpl的文章!tmpl的產(chǎn)生也正是解決這個問題的!我很自知這個方法沒tmpl強(qiáng)大,但tmpl有一個問題沒有解決,其實(shí)模板有兩個主要的問題,1是如果模板存儲在js里不好編輯,2是要把模板存儲在哪里才方便設(shè)計(jì)時的視圖呢!tmpl把模板存儲在<script type="text/x-jquery-tmpl"></script>標(biāo)簽中,應(yīng)該說是解決了第一個問題,但我感覺第2個問題也是很重要的!想來想去,只能把模板直接存儲在數(shù)據(jù)的容器標(biāo)記里:
復(fù)制代碼 代碼如下:
<ul id="ulList">
<li><a href="somepage.html?id={ID}">{Title}</a><br />
{Content}</li>
</ul>
把模板直接寫在目標(biāo)容器里,就像一條數(shù)據(jù)一樣,美工調(diào)樣式不是問題,程序加方法不是問題,這方法我看行!但js肯定不會直接操作這個模板吧,現(xiàn)在要做的就是把這個模板變成真的模板:
復(fù)制代碼 代碼如下:
$(function() {
var ulList = $("#ulList");
ulList.data("tpl",ulList.html()).empty();
}
把模板存儲到容器的data里應(yīng)該是再適當(dāng)不過了,而且這個操作在頁面加載完馬上就做!然后把容器清空,讓位給后來加載過來的真實(shí)數(shù)據(jù)。后臺提供json數(shù)據(jù),這個很簡單:
復(fù)制代碼 代碼如下:
public class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
//handler里用了上面第一個問題的解決方法
hs.Add("getNews", delegate()
{
List<News> list = new List<News>()
{
new News(){ ID=1,Title="title1",Content="Content1"},
new News(){ ID=2,Title="title2",Content="Content2"},
new News(){ ID=3,Title="title3",Content="Content3"},
};
return jss(list);
});
前臺取數(shù)據(jù)沒什么好說的,這個很基本:
復(fù)制代碼 代碼如下:
$.get("Handler.ashx?n=" + Math.random(), { action: "getNews" }, function(data) {
var list = $.parseJSON(data);
var ul = $("#ulList");
var html = "";
for (var i = 0; i < list.length; i++) {
html += ul.data("tpl").format(list[i]);
}
ul.html(html);
})
在填充數(shù)據(jù)的時候用了string.format這個方法,它在我js中的string.format 隨筆里有記錄,呵呵,這個我也沒有想到,寫format的時候讓它支持json對象只是為了閱讀方便,然而用到這如此合適!到這的時候我已興奮不已了,測試結(jié)果如下:
從沒有這么認(rèn)真的寫過隨筆,三個星期就休息了這一下午,沒陪女朋友,沒睡大覺,沒找朋友喝酒,卻老老實(shí)實(shí)地把它完成了!
相關(guān)文章
Jquery動態(tài)進(jìn)行圖片縮略的原理及實(shí)現(xiàn)
圖片縮略在某些情況下還是比較實(shí)用的,比如在做一些商品的預(yù)覽圖縮略等等,下面為大家介紹下具體的實(shí)現(xiàn)思路及代碼,有需求的朋友可以參考下2013-08-08js頁面滾動時層智能浮動定位實(shí)現(xiàn)(jQuery/MooTools)
關(guān)于層的智能浮動效果早在幾年前我就在國外的一些個人網(wǎng)站的垂直導(dǎo)航上見到了,現(xiàn)在似乎在國內(nèi)一些商業(yè)網(wǎng)站上也屢見此效果2011-08-08jQuery調(diào)取jSon數(shù)據(jù)并展示的方法
這篇文章主要介紹了jQuery調(diào)取jSon數(shù)據(jù)并展示的方法,實(shí)例分析了jQuery調(diào)用json數(shù)據(jù)及展示的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-01-01jQuery實(shí)現(xiàn)div跟隨鼠標(biāo)移動
這篇文章主要為大家詳細(xì)介紹了jQuery實(shí)現(xiàn)div跟隨鼠標(biāo)移動,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05jQuery插件實(shí)現(xiàn)靜態(tài)HTML驗(yàn)證碼校驗(yàn)
這篇文章主要介紹了jQuery插件實(shí)現(xiàn)靜態(tài)HTML驗(yàn)證碼校驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2015-11-11