關於html+ashx開發中幾個問題的解決方案

來源:互聯網
上載者:User

問題1:用委託字典代替switch...case。

  這個問題是在處理請求時發現的,大家肯定也不願意在自己的項目中建許多的handler來處理那麼多的請求,於是就想到在一個handler裡處理多個請求,ajax請求中都加一個action的參數,在handler雷根據這個action做相應的處理或返回相應的資料,這裡肯定沒有人用if...else來判斷action,大多數人都會想到用switch...case,一開始我也是用的switch,但漸漸地發現,每個case不像一個代碼塊,不能為其中的變數提供一個獨立的範圍!用龍珠中孫悟空的話“真是傷腦筋”。

  在網上搜了一下,也有不少人遇到這個問題。有個解決方案是把每個處理單獨成handler裡一個方法,這樣清楚明了,但在ProcessRequest方法中要用反射調用對應的方法!自己對這個解決辦法不太滿意,於是想到了委託,想到了字典,把反射調用方法變成在字典裡索引委託。

  首先在handler裡聲明一個私人的靜態委託字典:

  static Dictionary<string, Func<string>> hs;
  然後用handler(一般處理常式的類)裡靜態建構函式初始化hs,更重要的是要在靜態建構函式裡添加處理方法:
複製代碼 代碼如下:
  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方法裡調用了:
複製代碼 代碼如下:
  context.Response.ContentType = "text/plain";
  HttpRequest req = context.Request;
  string action = req["action"].ToLower();
  string result = hs[action]();
  context.Response.Write(result);

  這樣便避免了switch...case的變數範圍問題和反射的效率問題。關於上面用到的req()方法,我的想法是把公用的東西用靜態方法提供,如:
複製代碼 代碼如下:
  static string req(string key)
  {
    return HttpContext.Current.Request[key];
  }
  static string jss(object obj)
  {
    JavaScriptSerializer JSS = new JavaScriptSerializer();
    return JSS.Serialize(obj);
  }

問題2:許可權問題。

  你肯定不願自己的資料在使用者沒有登陸或登陸到期後還可以繼續訪問。這裡假設登陸的使用者用Session["user"]來儲存,當然在handler裡判斷一下Session["user"]是很簡單的事情,但問題是你如何讓Session["user"]為null時的使用者跳轉到指定頁(這裡假設是登陸頁login.html)。哈哈,這時你會不會想到用context.Response.Redirect ("login.html")這樣一句話來解決呢!我的第一反映是這樣的,但分析一下,ajax是請求資料的,這樣做是讓ajax去請求login.html這個頁面,得到的結果應該是login.html的原始碼才對,分析是這樣分析的,可還是不死心,還是測試了一下,結果正如分析的那樣,login.html的原始碼做為ajax請求結果返回了!

  其實,大家心理明白,有一個很簡單的方法,就是在Session["user"]為null時返回一個特定值,這裡假設"unlogin",然後在每次ajax請求完成後判斷傳回值是不是"unlogin"。

這方法很簡單,也很可靠,但很笨,很麻煩,可行性不高。於是我又想到了jquery.ajaxSuccess(),想用它來做統一處理,在我想到它的時候我就有點兒擔心,jquery會不會是先調用具體請求的回呼函數然後再調用這全域的回呼函數呢?我帶著這個疑問做了測試,結果也如預料那樣先執行具體請求的回調再執行全域回調!沒法辦,只好查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 );
    }
  }

  執行順序是改好了,可跳轉的代碼寫哪呢?每個頁面寫一次?不不,這不是我們寫程式的風格,思來想去,寫到jquery檔案裡(最下面)是一個可行的方法:
複製代碼 代碼如下:
$(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:資料範本。

  真是什麼東西需要,什麼都東西就應運而生!在寫這個隨筆之前正好在園裡看到了個jquery.tmpl的文章!tmpl的產生也正是解決這個問題的!我很自知這個方法沒tmpl強大,但tmpl有一個問題沒有解決,其實模板有兩個主要的問題,1是如果模板儲存在js裡不好編輯,2是要把模板儲存在哪裡才方便設計時的視圖呢!tmpl把模板儲存在<script type="text/x-jquery-tmpl"></script>標籤中,應該說是解決了第一個問題,但我感覺第2個問題也是很重要的!想來想去,只能把模板直接儲存在資料的容器標記裡:
複製代碼 代碼如下:
<ul id="ulList">
<li><a href="somepage.html?id={ID}">{Title}</a><br />
{Content}</li>
</ul>

   把模板直接寫在目標容器裡,就像一條資料一樣,美工調樣式不是問題,程式加方法不是問題,這方法我看行!但js肯定不會直接操作這個模板吧,現在要做的就是把這個模板變成真的模板:
複製代碼 代碼如下:
  $(function() {
    var ulList = $("#ulList");
    ulList.data("tpl",ulList.html()).empty();
  }

  把模板儲存到容器的data裡應該是再適當不過了,而且這個操作在頁面載入完馬上就做!然後把容器清空,讓位給後來載入過來的真實資料。後台提供json資料,這個很簡單:
複製代碼 代碼如下:
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);
  });

  前台取資料沒什麼好說的,這個很基本:
複製代碼 代碼如下:
$.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);
})

  在填充資料的時候用了string.format這個方法,它在我js中的string.format 隨筆裡有記錄,呵呵,這個我也沒有想到,寫format的時候讓它支援json對象只是為了閱讀方便,然而用到這如此合適!到這的時候我已興奮不已了,測試結果如下:

但當我加了事件後,我發現還不夠好。如果在模板li裡加上onclick="show({ID},'{Title}')",IE裡剛開啟頁面的時候就會有js錯誤,這是為什麼呢?問題在這個ID參數上,因為{ID}被看作json對象了,而它卻是一個格式不對的json! 提示js錯誤也正常,'{Title}'沒有錯誤是原因這裡看作字串參數了。這個js錯誤雖然不影響程式,但沒有人不喜歡自己寫的代碼是沒有js錯誤的! 解決方案很簡單,像Title參數一樣加引號就可以了,如果show方法裡真的要數字類型,只好在那裡轉換一下嘍!不過你肯定會發現,很多時候是不用轉換的,甚至你還希望它就是個字串類型呢!

  從沒有這麼認真的寫過隨筆,三個星期就休息了這一下午,沒陪女朋友,沒睡大覺,沒找朋友喝酒,卻老老實實地把它完成了!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.