????? 這篇我來講如何實現自定義特性ajax,以及如何自動生成客戶端js。
?????
????? 第一:所謂的自定義特性,就是我們自己定義的一個特性標簽,在.net中,就有一些這樣的特性,例如 .net內置的System.ObsoleteAttribute 。示例代碼如下:
????????
????????public?void?testObsolete()
????????{?}
????????public?void?testObsolete(int?j)
????????{?}
????????public?void?testA()
????????{
????????????this.testObsolete();
????????}
??????
????????? 如果存在一個方法的多個重載,又不能刪除某些重載,可以給它加上Obsolete,當用戶調用這個方法時,編譯器就會給出警告提示用戶。這個類繼承自Attribute,特性是一個對象,可以加載到程序集及程序集的對象中,包括程序集本身、模塊、類、接口、結構、構造函數、方法、方法參數等,加載了特性的對象稱作特性的目標。特性為程序添加元數據(描述數據的數據)的一種機制,它可以給編譯器提供指示或者提供對數據的說明。
???????
????????? 特性有以下三個非常實用的參數以及屬性:[AttributeUsage(AttributeTargets.Class, AllowMutiple=true, Inherited=false)]
?????????? ?1:AttributeTargets代表特性應用的對象,類,接口,方法等。
?????????? ?2:AllowMutiple,是否允許用戶在一個對象上多次使用特性標簽。
?????????? ?3:Inherited:對于子類是否有效。
????????
??????????這里我們創建一個AjaxAttribute.cs類,包含三個簡單屬性。
???public??class?AjaxAttribute:Attribute
????{
????????public?string?Name?{?get;?set;?}
????????public?bool?Inherited{get;set;}
????????public?AjaxReturnType?ReturnType?{?get;?set;?}
????}
?
?????? 第二:上篇文章(asp.net mvc(八))我們提到,MVC中實現ajax,可以返回JsonResult類型的值供客戶端調用,但它返回的是查詢出來的直接對象,如果對象為空,則不會有實際內容返回。這個對象提供的信息可以擴充下,創建一個AjaxResult對象,繼承自JsonResult,有三個構造函數。 客戶端在調用回調方法時可以根據這些新增加的值來處理。
????????? 1:可以在返回結果對象中增加一個操作狀態值,一般可以是成功或者是失敗(success)。
????????? 2:可以在返回結果對象中增加一些提示信息,例如失敗的原因之類信息(message)。
???????? ?3: 可以在返回結果對象中增加一個類型為object的屬性,用來保存程序返回的數據(object value)。
???????
????{
????????public?AjaxResult(bool?isSuccess)
????????{
????????????AjaxInfo?info?=?new?AjaxInfo();
????????????info.success?=?isSuccess;
????????????this.Data?=?info;
????????}
????????public?AjaxResult(bool?isSuccess,?object?data)
????????{
????????????AjaxInfo?info?=?new?AjaxInfo();
????????????info.success?=?isSuccess;
????????????info.value?=?data;
????????????this.Data?=?info;
????????}
????????public?AjaxResult(bool?isSuccess,?object?data,?string?messsage)
????????{
????????????AjaxInfo?info?=?new?AjaxInfo();
????????????info.success?=?isSuccess;
????????????info.value?=?data;
????????????info.message?=?messsage;
????????????this.Data?=?info;
????????}
????}
????public?class?AjaxInfo
????{
????????public?bool?success?{?get;?set;?}
????????public?string?message?{?get;?set;?}
????????public?object?value?{?get;?set;?}
????}
????
java html、??
????? 第三:提供多種返回類型,之前的示例返回json格式,顯然有局限性,為此可以創建一個返回值類型的枚舉,以支持多種格式的數據。當返回類型不同時,異常調用方法的返回類型也需要跟著變化。
????
????///?Ajax方法的返回類型
????///?</summary>
????public?enum?AjaxReturnType
????{
????????///?<summary>
????????///?返回一個可以由jQuery對象處理的XML文檔
????????///?</summary>
????????Xml,
????????///?<summary>
????????///?返回純文本格式的HTML,包括求值后的腳本標記
????????///?</summary>
????????Html,
????????///?<summary>
????????///?將響應作為JSON求值,并返回一個Javascript對象
????????///?</summary>
????????Json,
????????///?<summary>
????????///?將響應作為Javascript語句求值,并返回純文本
????????///?</summary>
????????Script
????}
?
????
?????? 第四:利用反射以及結合我們創建的自定義特性AjaxAttribute,完成js代碼的輸出。這段代碼比較多,大家可以自己去試試。
????
????{
????????private?string?_Script;
????????private?Dictionary<string,?AjaxMethodInfo>?_AjaxMethods;
????????private?List<PropertyInfo>?_AjaxProperties;
???????///?<summary>
???????///?利用反射,創建js腳本
???????///?</summary>
???????///?<param?name="type"></param>
???????public?AjaxClass(Type?type)
???????{
???????????List<string>?scripts?=?new?List<string>();
???????????Dictionary<string,?AjaxMethodInfo>?methodList?=?new?Dictionary<string,?AjaxMethodInfo>();
???????????List<PropertyInfo>?propertyList?=?new?List<PropertyInfo>();
???????????MethodInfo[]?methods;
???????????PropertyInfo[]?properties;
???????????string?clientName;
???????????object[]?attrs?=?type.GetCustomAttributes(typeof(AjaxAttribute),?false);
???????????if?(attrs.Length?>?0)
???????????{
???????????????AjaxAttribute?attr?=?attrs[0]?as?AjaxAttribute;
???????????????clientName?=?string.IsNullOrEmpty(attr.Name)???type.Name?:?attr.Name;
???????????????if?(attr.Inherited)
???????????????{
???????????????????methods?=?type.GetMethods(BindingFlags.Public?|?BindingFlags.Instance);
???????????????????properties?=?type.GetProperties(BindingFlags.Public?|?BindingFlags.Instance?|?BindingFlags.GetProperty);
???????????????}
???????????????else
???????????????{
???????????????????methods?=?type.GetMethods(BindingFlags.Public?|?BindingFlags.Instance?|?BindingFlags.DeclaredOnly);
???????????????????properties?=?type.GetProperties(BindingFlags.Public?|?BindingFlags.Instance?|?BindingFlags.GetProperty?|?BindingFlags.DeclaredOnly);
???????????????}
???????????}
???????????else
???????????{
???????????????clientName?=?type.Name;
???????????????methods?=?type.GetMethods(BindingFlags.Public?|?BindingFlags.Instance?|?BindingFlags.DeclaredOnly);
???????????????properties?=?type.GetProperties(BindingFlags.Public?|?BindingFlags.Instance?|?BindingFlags.GetProperty?|?BindingFlags.DeclaredOnly);
???????????}
???????????foreach?(MethodInfo?mi?in?methods)
???????????{
???????????????attrs?=?mi.GetCustomAttributes(typeof(AjaxAttribute),?false);
???????????????if?(attrs.Length?>?0)
???????????????{
???????????????????AjaxReturnType?returnType?=?AjaxReturnType.Html;
???????????????????if?(mi.ReturnType?==?typeof(int)?||?mi.ReturnType?==?typeof(System.Web.Mvc.JsonResult))
???????????????????????returnType?=?AjaxReturnType.Json;
???????????????????//AjaxReturnType?returnType?=?(attrs[0]?as?AjaxAttribute).ReturnType;
???????????????????AjaxMethodInfo?ami?=?new?AjaxMethodInfo(mi,?returnType);
???????????????????methodList.Add(mi.Name,?ami);
???????????????????scripts.Add(BuildAjaxRequest(ami));
???????????????}
???????????}
???????????foreach?(PropertyInfo?pi?in?properties)
???????????{
???????????????attrs?=?pi.GetCustomAttributes(typeof(AjaxAttribute),?false);
???????????????if?(attrs?!=?null?&&?attrs.Length?>?0)?propertyList.Add(pi);
???????????}
???????????if?(methodList.Count?>?0)?_AjaxMethods?=?methodList;
???????????if?(propertyList.Count?>?0)?_AjaxProperties?=?propertyList;
???????????BuildScript(clientName,?scripts,?propertyList);
???????}
???????///?<summary>
???????///?輸入所有屬性的js腳本
???????///?</summary>
???????///?<param?name="obj"></param>
???????///?<returns></returns>
???????public?string?GetScript(object?obj)
???????{
???????????if?(_AjaxProperties?==?null)?return?_Script;
???????????string?script?=?string.Empty;
???????????foreach?(PropertyInfo?pi?in?_AjaxProperties)
???????????{
???????????????if?(script?==?string.Empty)?script?=?BuildAjaxObject(obj,?pi);
???????????????else?script?+=?",\r\n????????????"?+?BuildAjaxObject(obj,?pi);
???????????}
???????????return?_Script.Replace("{property}",?script);
???????}
???????///?<summary>
???????///?創建最終的js腳本
???????///?</summary>
???????///?<param?name="typeName"></param>
???????///?<param?name="scripts"></param>
???????///?<param?name="propertyList"></param>
???????private?void?BuildScript(string?typeName,?List<string>?scripts,?List<PropertyInfo>?propertyList)
???????{
???????????if?(scripts.Count?>?0?||?propertyList.Count?>?0)
???????????{
???????????????StringBuilder?sb?=?new?StringBuilder();
???????????????sb.AppendLine();
???????????????sb.AppendLine("???????<script?type=\"text/javascript\">");
???????????????sb.AppendFormat("????????var?{0}?=?{{",?typeName);
???????????????if?(propertyList.Count?>?0)
???????????????{
???????????????????sb.AppendLine();
???????????????????sb.Append("????????????{property}");
???????????????}
???????????????for?(int?i?=?0;?i?<?scripts.Count;?i++)
???????????????{
???????????????????if?(i?==?0?&&?propertyList.Count?==?0)?sb.AppendLine();
???????????????????else?sb.AppendLine(",");
???????????????????sb.Append("????????????"?+?scripts[i]);
???????????????}
???????????????sb.AppendLine();
???????????????sb.AppendLine("????????}");
???????????????sb.AppendLine("?????</script>");
???????????????_Script?=?sb.ToString();
???????????}
???????}
???????///?<summary>
???????///?jquery相關ajax方法的腳本構建
???????///?</summary>
???????///?<param?name="ami"></param>
???????///?<returns></returns>
???????private?string?BuildAjaxRequest(AjaxMethodInfo?ami)
???????{
???????????string?methodName?=?ami.MethodInfo.Name;
???????????string?url?=?"{url}"?+?methodName?+?"{querystring}";
???????????ParameterInfo[]?parameters?=?ami.MethodInfo.GetParameters();
???????????AjaxReturnType?returnType?=?ami.ReturnType;
???????????string?param,?data;
???????????if?(parameters?==?null?||?parameters.Length?==?0)
???????????{
???????????????param?=?"callback";
???????????????data?=?string.Empty;
???????????}
??????????if?(parameters.Length?==?0)
???????????{
???????????????return?string.Format(@"{0}:?function(callback)
????????????????????????????????????????????????{{
?????????????????????????????????????????????????????$.getJSON('{1}',?callback);
????????????????????????????????????????????????}}",
???????????????????????????methodName,?url);
???????????}
???????????else
???????????{
???????????????string[]?paramArray?=?new?string[parameters.Length?+?1];
???????????????string[]?dataArray?=?new?string[parameters.Length];
???????????????for?(int?i?=?0;?i?<?parameters.Length;?i++)
???????????????{
???????????????????paramArray[i]?=?parameters[i].Name;
???????????????????dataArray[i]?=?string.Format("{0}:{0}",?parameters[i].Name);
???????????????}
???????????????//paramArray[parameters.Length]?=?"callback";
???????????????param?=?string.Join(",?",?paramArray);
???????????????param?=?param.Trim?().TrimEnd(',');
???????????????data?=?string.Join(",?",?dataArray);
???????????}
???????????return?string.Format(@"{0}:?function({1},callback)
????????????????????????????????????????????????{{
?????????????????????????????????????????????????????$.getJSON('{2}',{{{3}}},?callback);
????????????????????????????????????????????????}}",
???????????????????????????methodName,param,?url,data);
???????}
???????private?string?BuildAjaxObject(object?obj,?PropertyInfo?pi)
???????{
???????????object?value?=?pi.GetValue(obj,?null);
???????????object[]?attrs?=?pi.GetCustomAttributes(typeof(AjaxAttribute),?false);
???????????if?(attrs.Length?>?0)
???????????{
???????????????AjaxAttribute?attr?=?attrs[0]?as?AjaxAttribute;
???????????????if?(attr.ReturnType?==?AjaxReturnType.Json?&&?value?is?string)
???????????????????return?string.Format(@"{0}:?{1}",?pi.Name,?value);
???????????}
???????????StringBuilder?sb?=?new?StringBuilder();
???????????JsonWriter?jw?=?new?JsonWriter(sb);
???????????jw.Write(value);
???????????return?string.Format(@"{0}:?{1}",?pi.Name,?sb.ToString());
???????}
????}
????
?
mvc 頁面管理。????? 第五:為了讓所有頁面都能利用js自動代碼生成,我為所有Controller創建一個基類,在它的Initialize中初始化js腳本。
????
????{
???????protected?override?void?Initialize(RequestContext?requestContext)
???????{
???????????base.Initialize(requestContext);
???????????InitJavaScript();
???????}
????????///?<summary>
????????///?初始化Ajax使用的JavaScript
????????///?</summary>
????????private?void?InitJavaScript()
????????{
????????????string?jsb?=?AjaxManager.GetAjaxScript(this);
????????????string?controller?=?Convert.ToString(this.RouteData.Values["controller"]);
????????????if?(!string.IsNullOrEmpty(jsb)?&&?!string.IsNullOrEmpty(controller))
????????????{
????????????????string?str?=?System.Web.HttpContext.Current.Request.ApplicationPath;
????????????????str?=?str.Length?>?1???str?:?string.Empty;
????????????????jsb?=?jsb.Replace("{url}",?string.Format("{0}/{1}/",?str,?controller));
????????????????jsb?=?jsb.Replace("{querystring}",?GetHttpQueryString());
????????????}
????????????ViewData["m_javablock"]?=?jsb;
????????}
????????private?string?GetHttpQueryString()
????????{
????????????StringBuilder?sb?=?new?StringBuilder("?");
????????????foreach?(KeyValuePair<string,?object>?pair?in?this.RouteData.Values)
????????????{
????????????????if?(pair.Key?!=?"controller"?&&?pair.Key?!=?"action")
????????????????????sb.AppendFormat("{0}={1}&",?pair.Key,?(pair.Value!=null)?pair.Value.ToString():"");
????????????}
????????????sb.Append(System.Web.HttpContext.Current.Request.QueryString.ToString());
????????????return?sb.ToString();
????????}
????}
????
????public??class?AjaxManager
????{
????????public?static?string?GetAjaxScript(object?obj)
????????{
????????????AjaxClass?ajaxClass?=?new?AjaxClass(obj.GetType());
????????????return?ajaxClass.GetScript(obj);
????????}
????}
???
???? 第六:在HomeController類中,增加如下用于異步請求的代碼。同時在方法上面增加特性標簽Ajax。
??
????????public?AjaxResult?TestMVC(int?i,?int?j)
????????{
????????????int?I?=?0;
????????????List<student>?list?=?new?List<student>();
????????????for?(int?k?=?0;?k?<?10;?k++)
????????????{
????????????????student?sd?=?new?student()?{?sname?=?"aaa"?+?k.ToString()?+?j.ToString(),?ID?=?k,?Grade?=?k?*?10?};
????????????????list.Add(sd);
????????????}
????????????var?stu?=?(from?m?in?list
???????????????????????where?m.ID?==?i
???????????????????????select?m
?????????????????????????).FirstOrDefault();
????????????return?new?AjaxResult(true,?stu);
????????}
????????
?
?? ??? 第七:最終生成的客戶端js如下:
????????var?HomeController?=?{
????????????TestMVC:?function(i,?j,callback)
????????????????????????????????????????????????{
?????????????????????????????????????????????????????$.getJSON('/Home/TestMVC?id=&',{i:i,?j:j},?callback);
????????????????????????????????????????????????}
????????}
?????</script>
?
mvc和mvvm、?????? 總結:上面的代碼可能寫的比較亂,但大概思路應該有了,這樣我們可以在后臺代碼中為需要異步調用的方法增加Ajax特性標簽,然后在客戶端通過類型C#命令空間的方式調用。例如:
?????
?????????????$("#divStudent").html(data.value.sname);
?????????????});
?
?
作者:姜敏
出處:http://www.cnblogs.com/aspnet2008/