• 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/

     

  • 相关阅读:
    关于UITapGestureRecognizer的一些问题
    自定义导航栏返回按钮
    mousewheel滚轮事件 浏览器的写法
    Apache日志不记录图片文件设置方法和来源日志的配置
    redis持久化配置
    haproxy实现负载均衡
    Keepalived高可用软件的安装与配置
    Sublime text2用户自定义配置
    判断各版本的最简写法
    Ubuntu防火墙 UFW 设置
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1680049.html
Copyright © 2020-2023  润新知