zoukankan      html  css  js  c++  java
  • asp.net mvc(九)

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

    代码
           [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类,包含三个简单属性。

    代码
       [AttributeUsage(AttributeTargets.All,AllowMultiple=true )]
       
    public  class AjaxAttribute:Attribute
        {
            
    public string Name { getset; }
            
    public bool Inherited{get;set;}
            
    public AjaxReturnType ReturnType { getset; }
        }

     
           第二:上篇文章(asp.net mvc(八))我们提到,MVC中实现ajax,可以返回JsonResult类型的值供客户端调用,但它返回的是查询出来的直接对象,如果对象为空,则不会有实际内容返回。这个对象提供的信息可以扩充下,创建一个AjaxResult对象,继承自JsonResult,有三个构造函数。 客户端在调用回调方法时可以根据这些新增加的值来处理。


              1:可以在返回结果对象中增加一个操作状态值,一般可以是成功或者是失败(success)。
              2:可以在返回结果对象中增加一些提示信息,例如失败的原因之类信息(message)。
              3: 可以在返回结果对象中增加一个类型为object的属性,用来保存程序返回的数据(object value)。
           

    代码
    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 { getset; }

            
    public string message { getset; }

            
    public object value { getset; }
        }
        

      

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

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

    代码
    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[0as 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 == nullreturn _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[0as 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脚本。
        

    代码
    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<stringobject> 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。
      

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

    代码
        <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/

     

  • 相关阅读:
    盒子垂直水平居中
    Sahi (2) —— https/SSL配置(102 Tutorial)
    Sahi (1) —— 快速入门(101 Tutorial)
    组织分析(1)——介绍
    Java Servlet (1) —— Filter过滤请求与响应
    CAS (8) —— Mac下配置CAS到JBoss EAP 6.4(6.x)的Standalone模式(服务端)
    JBoss Wildfly (1) —— 7.2.0.Final编译
    CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服务端)
    CAS (6) —— Nginx代理模式下浏览器访问CAS服务器网络顺序图详解
    CAS (5) —— Nginx代理模式下浏览器访问CAS服务器配置详解
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1680049.html
Copyright © 2011-2022 走看看