由於jquery的出現,編寫js代碼已經變得異常的平民化,同時現在的web也已經是ajax滿天飛,哪天你自己寫一個web不含ajax的拿不出手
當然,在.net的控制項模式開發中一種去控制項化開發已經變的變得更加通用:jquery+ajax+ashx 這種方式更加適用於一些小應用的開發,輕量、簡單、自由
由於那時候太年輕,剛剛開始這種模式開發的時候 是一個ajax請求一個ashx頁面,這樣的結果可想而知,一個小的許可權系統光光ashx檔案就幾十個了,而且檔案名稱還大同小異,悲劇。
後來做了一會兒變聰明了,把相同類別的請求都放到一個ashx檔案中,每個請求傳一個請求標誌 通過switch來調用相應的要求方法,當然,這樣要比原來好多了,至少沒那麼多ashx檔案了,但是 每建立一個檔案都要去添加switch方法,蛋疼啊 有木有,更加可恥的是 每次增刪改一個請求都要去修改那個可惡的switch語句,煩啊
後來知道了反射,知道可以用反射來動態調用方法,腦子一轉,哇 好主意,查了相關資料,沒幾分鐘就把這個架構寫了出來,然後百度一搜,次奧,關於這種的都有那麼多文章了,本來都不想再寫這篇文章,重複造輪子啊 要被罵的有木有,不過想想代碼都寫了,而且還是自己寫的,寫篇文章紀念一下,而且這個東西感覺比網上的更加方便,實用,嘿嘿。
下面就是這個handler主心骨雞類的詳解了
首先在這個雞類中定義幾個預設的參數
/// <summary> /// 指定過來的http請求類型 主要指定action方法名稱的接收方式 get 或者 post /// </summary> protected NameValueCollection _httpReuqest = HttpContext.Current.Request.Form; /// <summary> /// 指定返回頭 /// </summary> protected string _contentType = "text/plain"; /// <summary> /// 指定接收action方法的參數名稱 /// </summary> protected string _actionName = "action";
主要是定義預設的請求方式 GET或者POST 當然預設是POST,相對安全點嘛,並且個人用的也多,當然這個請求方式在子類中可以把它改掉呢
還有就是請求的返回頭,方法名稱的參數 代碼的注釋裡面都寫得很清楚呢
下面就是動態調用方法的核心代碼啦(再這裡給個反射串連的相關知識,不知道的點我哦)
//根據指定的請求類型擷取方法名 string action = this._httpReuqest[this._actionName]; if (!string.IsNullOrEmpty(action)) { //擷取方法的執行個體 非靜態 需要Public存取權限 忽略大小寫 MethodInfo methodInfo = this.GetType().GetMethod(action, BindingFlags.Instance|BindingFlags.Public|BindingFlags.IgnoreCase); if (methodInfo != null) { //調用方法 methodInfo.Invoke(this, null); } else { throw new ApplicationException(string.Format("沒有找到方法{0}", action)); } } else { throw new ArgumentNullException("沒有找到調用方法參數或者方法名為空白"); }
核心代碼夠簡單把 其實最核心的就是擷取方法執行個體,當然該方法,兩句啦 方便吧
我們看看這個擷取方法執行個體的代碼
主要是擷取類中的非靜態,公開訪問,忽略名稱大小寫方法,當然你如果不放心 其他的方法也被ajax跨域調用了,你可以給該方法的存取權限設為private或者protected 如果你還是不放心的話 可以喝其他的一樣 自訂一個Attribute特徵加在方法頭上,不過個人在這裡感覺沒啥必要了
核心的都給你們看了 那來看下雞類的全部代碼吧
/// <summary> /// Handler請求的基類 用此類動態調用請求的方法 /// </summary> public class HandlerBase : IHttpHandler { /// <summary> /// 指定過來的http請求類型 主要指定action方法名稱的接收方式 get 或者 post /// </summary> protected NameValueCollection _httpReuqest = HttpContext.Current.Request.Form; /// <summary> /// 指定返回頭 /// </summary> protected string _contentType = "text/plain"; /// <summary> /// 指定接收action方法的參數名稱 /// </summary> protected string _actionName = "action"; //擷取當前的http context protected HttpContext Context { get { return HttpContext.Current; } } public void ProcessRequest(HttpContext context) { context.Response.ContentType = this._contentType; try { //動態調用方法 當然 你還可以在這裡加上是否為同網域名稱請求的判斷 this.DynamicMethod(); } catch (AmbiguousMatchException amEx) { this.PrintErrorJson(string.Format("根據該參數{0}找到了多個方法",amEx.Message)); } catch (ArgumentException argEx) { this.PrintErrorJson("參數異常" + argEx.Message); } catch (ApplicationException apEx) { this.PrintErrorJson("程式異常" + apEx.Message); } } #region 動態調用方法 /// <summary> /// 動態調用方法 /// </summary> private void DynamicMethod() { //根據指定的請求類型擷取方法名 string action = this._httpReuqest[this._actionName]; if (!string.IsNullOrEmpty(action)) { //擷取方法的執行個體 非靜態 需要Public存取權限 忽略大小寫 MethodInfo methodInfo = this.GetType().GetMethod(action, BindingFlags.Instance|BindingFlags.Public|BindingFlags.IgnoreCase); if (methodInfo != null) { //調用方法 methodInfo.Invoke(this, null); } else { throw new ApplicationException(string.Format("沒有找到方法{0}", action)); } } else { throw new ArgumentNullException("沒有找到調用方法參數或者方法名為空白"); } } #endregion #region 列印Json的相關處理 /// <summary> /// 列印遇到異常的json /// </summary> /// <param name="msg"></param> protected void PrintErrorJson(string msg) { this.PrintJson("error", msg); } /// <summary> /// 列印成功處理的json /// </summary> /// <param name="msg"></param> protected void PrintSuccessJson(string msg) { this.PrintJson("success", msg); } /// <summary> /// 列印json /// </summary> /// <param name="state"></param> /// <param name="msg"></param> protected void PrintJson(string state, string msg) { this.Context.Response.Write("{\"state\":\""+state+"\",\"msg\":\"" + msg + "\"}"); } #endregion public bool IsReusable { get { return false; } } }
夠簡單把,然後寫幾個測試ashx頁面繼承該基類就可以啦
/// <summary> /// Get一般處理常式的測試 /// </summary> public class gethandler : HandlerBase { public gethandler() { //修改請求為get 方式 base._httpReuqest = base.Context.Request.QueryString; } /// <summary> /// 加法操作 /// </summary> public void Add() { int a = Convert.ToInt32(_httpReuqest["a"]); int b = Convert.ToInt32(_httpReuqest["b"]); PrintSuccessJson((a + b).ToString()); } /// <summary> /// 減法操作 /// </summary> private void Minus() { int a = Convert.ToInt32(_httpReuqest["a"]); int b = Convert.ToInt32(_httpReuqest["b"]); PrintSuccessJson((a - b).ToString()); } }
下面來個post類型的
/// <summary> /// Post一般處理常式的測試 /// </summary> public class posthandler : HandlerBase { public posthandler() { //修改請求為get 方式 base._httpReuqest = base.Context.Request.Form; } /// <summary> /// 乘法操作 /// </summary> public void Multiply() { int a = Convert.ToInt32(_httpReuqest["a"]); int b = Convert.ToInt32(_httpReuqest["b"]); PrintSuccessJson((a + b).ToString()); } /// <summary> /// 減法操作 /// </summary> public void Minus() { int a = Convert.ToInt32(_httpReuqest["a"]); int b = Convert.ToInt32(_httpReuqest["b"]); PrintSuccessJson((a - b).ToString()); } }
很容易看懂吧,前台的html頁面就不貼了
如果看的同學實在是看不懂 那趕緊猛擊我去下面源碼
還有設計不當之處請各位留言指正哦,共同進步哈