asp.net mvc(九)

      这篇我来讲如何实现自定义特性ajax,以及如何自动生成客户端js。
     
      第一:所谓的自定义特性,就是我们自己定义的一个特性标签,在.net中,就有一些这样的特性,例如 .net内置的System.ObsoleteAttribute 。示例代码如下:
        

ExpandedBlockStart.gif 代码
       [Obsolete( " 此方法已经过时 " )]
        
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类,包含三个简单属性。

ExpandedBlockStart.gif 代码
   [AttributeUsage(AttributeTargets.All,AllowMultiple = true  )]
   
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)。
       

ExpandedBlockStart.gif 代码
public   class  AjaxResult : JsonResult
    {
        
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 ; }
    }
    

  

      第三:提供多种返回类型,之前的示例返回json格式,显然有局限性,为此可以创建一个返回值类型的枚举,以支持多种格式的数据。当返回类型不同时,异常调用方法的返回类型也需要跟着变化。
    

ExpandedBlockStart.gif 代码
  ///   <summary>
    
///  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代码的输出。这段代码比较多,大家可以自己去试试。
    

ExpandedBlockStart.gif 代码
public    class  AjaxClass
    {
        
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());
       }
    }
    

 

      第五:为了让所有页面都能利用js自动代码生成,我为所有Controller创建一个基类,在它的Initialize中初始化js脚本。
    

ExpandedBlockStart.gif 代码
public    class  BaseController: System.Web.Mvc.Controller
    {
       
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。
  

ExpandedBlockStart.gif 代码
        [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如下:

ExpandedBlockStart.gif 代码
     < script type = " text/javascript " >
        var HomeController 
=  {
            TestMVC: function(i, j,callback)
                                                {
                                                     $.getJSON(
' /Home/TestMVC?id=& ' ,{i:i, j:j}, callback);
                                                }
        }
     
</ script >

 

       总结:上面的代码可能写的比较乱,但大概思路应该有了,这样我们可以在后台代码中为需要异步调用的方法增加Ajax特性标签,然后在客户端通过类型C#命令空间的方式调用。例如:
     

HomeController.TestMVC(j,j + 1 , function(data) {
             $(
" #divStudent " ).html(data.value.sname);
             });

 

 


作者:姜敏
出处:http://www.cnblogs.com/aspnet2008/

 

转载于:https://www.cnblogs.com/ASPNET2008/archive/2010/03/07/1680049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值