上一篇:http://www.BkJia.com/kf/201203/122299.html
為什麼要這樣做?對比其它實現方式的優勢?
有不少朋友問到這些問題,所以這篇先把這兩個問題先解釋一下。後台處理Ajax請求無論使用aspx、asmx、ashx、還是IHttpHandler來處理,情況都跟下面差不多:
//aspx、asmx、ashx、IHttpHandler中的方法
public string GetMemberName(int id){
return new Member().GetMemberName(id);
}
public class Member{
public string GetMemberName(int id){
//do something with id;
return memberName;
}
}
也就是說,無論我們使用哪種實現,基本上都是一個轉接,將接收到的請求轉接到對應的業務類中處理(除非您的項目不介意業務代碼分散在aspx、asmx、ashx、IHttpHandler等各個角落)。
而文章中提出的這種方法,就是希望能夠創建一個中間代理將請求直接轉接到業務類的方法上,只需要在業務類中定義好方法,前端就可以直接通過指定的鏈接調用,不需要再去定義一個aspx或ashx。
接下來再來介紹這篇文章我們要實現的內容。
為什麼要這使用特性Attribute?
上篇文章中有朋友回復說接收的參數只支持Form提交的數據,能不能加上QueryString?當然是可以的,所以我們在這裡引入了特性Attribute,用來解決傳入參數的取值問題。
為了方便以後的擴展,我們首先定義了一個抽象類ParameterAttribute。
定義ParameterAttribute:
[AttributeUsage(AttributeTargets.Parameter)]
public abstract class ParameterAttribute : Attribute {
public object DefaultValue { get; set; }
public string Name { get; set; }
public ParameterAttribute() { }
public ParameterAttribute(string name, object defaultValue) {
Name = name;
DefaultValue = defaultValue;
}
public virtual object GetValue(System.Web.HttpContext context, Type parameterType) {
object value = GetParameterValue(context) ?? DefaultValue;
if (parameterType.FullName == "System.String") {
return value;
}
if (value.GetType().FullName == "System.String") {
if (string.IsNullOrEmpty((string)value)) {
value = DefaultValue;
}
}
return Convert.ChangeType(value, parameterType);
}
public abstract object GetParameterValue(System.Web.HttpContext context);
}
ParameterAttribute類繼承自Attribute,並且限定了該類只能應用到參數上。同時還定義了一個屬性DefaultValue,一個抽象方法GetParameterValue,有的朋友可能會問為什麼DefaultValue不用泛型實現,原因是繼承自Attribute的類不能使用泛型。
下面我們再定義一個FormAttribute來處理通過Form方式提交的參數。
定義FormAttribute:
public class FormAttribute : ParameterAttribute {
public FormAttribute() { }
public FormAttribute(string name) : base(name, null) { }
public FormAttribute(string name, object defaultValue) : base(name, defaultValue) { }
public override object GetParameterValue(System.Web.HttpContext context) {
return context.Request.Form[Name];
}
}
實際上這個類的定義很簡單,僅僅是返回一個Request.Form中的值而已,既然如此,那QueryString實現起來也是一件很簡單的事情了,改改名稱得到QueryStringAttribute:
定義QueryStringAttribute:
public class QueryStringAttribute : ParameterAttribute {
public QueryStringAttribute() { }
public QueryStringAttribute(string name) : base(name, null) { }
public QueryStringAttribute(string name, object defaultValue) : base(name, defaultValue) { }
public override object GetParameterValue(System.Web.HttpContext context) {
return context.Request.QueryString[Name];
}
}
修改後的Factory.Execute方法:
void Execute(HttpContext context) {
//根據請求的Url,通過反射取得處理該請求的類
string url = context.Request.Url.AbsolutePath;
string[] array = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string typename = "Biz";
for (int x = 1; x < array.Length - 1; x++) {
typename += "." + array[x];
}
Type type = this.GetType().Assembly.GetType(typename, false, true);
if (type != null) {
//取得類的無參數構造函數
var constructor = type.GetConstructor(new Type[0]);
//調用構造函數取得類的實例
var obj = constructor.Invoke(null);
//查找請求的方法
var method = type.GetMethod(System.IO.Path.GetFileNameWithoutExtension(url));
if (method != null) {
var parameters = method.GetParameters();
object[] args = null;
if (parameters.Length > 0) {
args = new object[parameters.Length];
for (int x = 0; x < parameters.Length; x++) {
var parameterAttr = (Attribute.GetCustomAttribute(parameters[x], typeof(ParameterAttribute)) as ParameterAttribute) ?? new FormAttribute();
parameterAttr.Name = parameterAttr.Name ?? parameters[x].Name;
args[x] = parameterAttr.GetValue(context, parameters[x].ParameterType);
}
}
//執行方法並輸出響應結果
context.Response.Write(method.Invoke(obj, args));
}
}
}
僅僅是比上次示例的代碼多了兩行而已。在沒有定義ParameterAttribute的情況下默認使用FormAttribute。
為了方便演示代碼,我們修改了Javascript代碼。
修改後的前端Javascript代碼:
$(function () {
//綁定按鈕點擊事件
$("#btnAction").click(function () {
$.post("/Ajax/News/Plus.aspx?y=" + $("input[name='y']").val() + "&num3=" + $("input[name='z']").val(), { x: $("input[name='x']").val() }, function (txt) {
$("#result").val(txt);
}, "text");
});
});
上面可以看到,我們為了演示參數可以取別名,將參數z修改成了num3,Html代碼也稍作修改。
修改後的前端Html代碼:
<input type="text" name="x" value="1" class="txt" />
<input type="button" disabled="disabled" value="+" class="txt btn" />
<input type="text" name="y" value="2" class="txt" />
<input type="button" disabled="disabled" value="+" class="txt btn" />
<input type="text" name="z" value="" class="txt" />
<input id="btnAction" type="button" value="=" class="txt btn" />
<input type="text" readonly="readonly" id="result" class="txt" />
運行示例後,即可看到我們想要的效果了。至此,我們就已經解決了支持參數從QueryString取值的問題,同時還可以實現擴展從其它方式取值,比如:Cookie、Session、Application、甚至Database,這裡我就不再一一實現了,有興趣的朋友不妨自已動手試試?
示例項目源代碼:
點擊下載
幾天篇文章都是半夜整理的,還要附帶寫示例代碼,覺得有幫助的朋友不妨點下推薦給點鼓勵,謝謝!
未完待續...
摘自 狼Robot