Example #1
0
        /// <summary>获取类型文件的缓存时间</summary>
        public static int GetCacheDuration(this Type type)
        {
            ScriptAttribute attr = ReflectHelper.GetScriptAttribute(type);

            return((attr != null) ? attr.CacheDuration : 0);
        }
        //----------------------------------------------
        // 入口
        //----------------------------------------------
        /// <summary>处理 Web 方法调用请求</summary>
        public static void ProcessRequest(HttpContext context, object handler)
        {
            // 解析类型、方法、参数等信息
            // 对于aspx页面,执行时编译出来的是类似ASP.xxx_aspx的类,这不是我们想要处理的类,追溯处理父类(IMPORTANT!)
            var decoder = RequestDecoder.CreateInstance(context);
            var args    = decoder.ParseArguments();
            var type    = handler.GetType();

            if (type.FullName.StartsWith("ASP.") && type.BaseType != null)
            {
                type = type.BaseType;
            }
            var methodName = decoder.MethodName;
            var method     = ReflectHelper.GetMethod(type, methodName);
            var attr       = ReflectHelper.GetHttpApiAttribute(method);

            // 处理预留方法
            if (ProcessReservedMethod(context, type, methodName, args))
            {
                return;
            }

            // 普通方法调用
            try
            {
                // 检测方法可用性
                CheckMethod(context, method, attr, args);

                // 获取需要的参数
                var parameters = ReflectHelper.GetParameters(method, args);
                var p          = SerializeHelper.ToJson(parameters).ClearSpace().TrimStart('[').TrimEnd(']'); //.Replace("\"", "");
                var cacheKey   = string.Format("{0}-{1}-{2}", handler, method.Name, p);                       // 可考虑用 MD5 做缓存健名
                var expireDt   = DateTime.Now.AddSeconds(attr.CacheSeconds);

                // 获取方法调用结果并依情况缓存
                object result;
                if (attr.CacheSeconds == 0)
                {
                    result = method.Invoke(handler, parameters);
                }
                else
                {
                    result = CacheHelper.GetCachedObject <object>(
                        cacheKey, expireDt,
                        () => { return(method.Invoke(handler, parameters)); }
                        );
                }

                // 输出结果
                ResponseType dataType = attr.Type;
                if (args.ContainsKey("_type"))
                {
                    dataType = (ResponseType)Enum.Parse(typeof(ResponseType), args["_type"].ToString(), true);
                }
                if (dataType == ResponseType.Auto && result != null)
                {
                    dataType = ParseDataType(result.GetType());
                }
                var wrap     = HttpApiConfig.Instance.Wrap ?? attr.Wrap;
                var wrapInfo = attr.WrapCondition;
                WriteResult(context, result, dataType, attr.MimeType, attr.FileName, attr.CacheSeconds, attr.CacheLocation, wrap, wrapInfo);
            }
            catch (Exception ex)
            {
                if (ex is HttpApiException)
                {
                    var err = ex as HttpApiException;
                    WriteError(context, err.Code, err.Message);
                }
                else
                {
                    var info = (ex.InnerException != null) ? ex.InnerException.Message : ex.Message;
                    WriteError(context, 400, info);
                }
                HttpApiConfig.Instance.DoException(method, ex);
            }
            finally
            {
                HttpApiConfig.Instance.DoEnd(context);
            }
        }
        /// <summary>访问对象</summary>
        private void VisitObject(StringBuilder sb, object obj, string name)
        {
            if (this.FormatLowCamel)
            {
                name = name?.ToLowCamel();
            }

            // 对象为空处理
            if (obj == null)
            {
                if (!name.IsNullOrEmpty())
                {
                    sb.AppendFormat("<{0}/>", name);
                }
                return;
            }

            // 正常处理
            var type = obj.GetType();

            if (type.IsNullable())
            {
                type = type.GetNullableDataType();
            }
            if (name.IsNullOrEmpty())
            {
                name = GetNodeName(type);
            }

            // 根据类型进行输出(还要判断可空类型)
            sb.AppendFormat("<{0}>", name);
            if (obj is string)
            {
                sb.Append(GetXmlSafeText(obj));
            }
            else if (obj is DateTime)
            {
                var dt = Convert.ToDateTime(obj);
                if (dt != new DateTime())
                {
                    sb.AppendFormat(dt.ToString(this.FormatDateTime));
                }
            }
            else if (type.IsEnum)
            {
                if (this.FormatEnum == EnumFomatting.Int)
                {
                    sb.AppendFormat("{0:d}", obj);
                }
                else
                {
                    sb.AppendFormat("{0}", obj);
                }
            }
            else if (obj is DataTable)
            {
                var table = obj as DataTable;
                var cols  = table.Columns;
                foreach (DataRow row in table.Rows)
                {
                    sb.AppendFormat("<Row>");
                    foreach (DataColumn col in cols)
                    {
                        var columnName = col.ColumnName;
                        VisitObject(sb, row[columnName], columnName);
                    }
                    sb.AppendFormat("</Row>");
                }
            }
            else if (obj is IDictionary)
            {
                var dict = (obj as IDictionary);
                foreach (var key in dict.Keys)
                {
                    sb.AppendFormat("<Item Key=\"{0}\">", key);
                    VisitObject(sb, dict[key], "");
                    sb.AppendFormat("</Item>");
                }
            }
            else if (obj is IEnumerable)
            {
                foreach (var item in (obj as IEnumerable))
                {
                    VisitObject(sb, item, "");
                }
            }
            else if (type.IsValueType)
            {
                sb.AppendFormat("{0}", obj);
            }
            else
            {
                var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach (var property in properties)
                {
                    if (ReflectHelper.GetAttribute <NonSerializedAttribute>(property) != null ||
                        ReflectHelper.GetAttribute <JsonIgnoreAttribute>(property) != null ||
                        ReflectHelper.GetAttribute <System.Xml.Serialization.XmlIgnoreAttribute>(property) != null
                        )
                    {
                        continue;
                    }

                    var subObj = property.GetValue(obj);
                    VisitObject(sb, subObj, property.Name);
                }
            }
            sb.AppendFormat("</{0}>", name);
        }
        // 预处理保留方法("js", "jq", "ext", "api", "apis")
        static bool ProcessReservedMethod(HttpContext context, Type type, string methodName, Dictionary <string, object> args)
        {
            string methodNameLower = methodName.ToLower();
            int    cacheDuration   = ReflectHelper.GetCacheDuration(type);

            // 输出api接口展示页面
            var lastChar = methodNameLower.Substring(methodNameLower.Length - 1);

            if (lastChar == "_" || lastChar == "$")
            {
                var name    = methodName.Substring(0, methodName.Length - 1);
                var typeapi = GetTypeApi(type);
                var api     = FindApi(typeapi, name);
                var result  = BuildApiHtml(api);
                context.Response.Clear();
                context.Response.ContentType = "text/html";
                context.Response.Write(result.ToString());
            }
            // 输出api接口测试页面
            else if (lastChar == "!")
            {
                var name    = methodName.Substring(0, methodName.Length - 1);
                var typeapi = GetTypeApi(type);
                var api     = FindApi(typeapi, name);
                var result  = BuildApiTestHtml(api);
                context.Response.Clear();
                context.Response.ContentType = "text/html";
                context.Response.Write(result.ToString());
            }
            else
            {
                // 保留方法名
                string[] arr = { "js", "jq", "ext", "api", "apis" };
                if (!((IList <string>)arr).Contains(methodNameLower))
                {
                    return(false);
                }

                // 输出api接口页面
                if (methodNameLower == "api")
                {
                    var typeapi = GetTypeApi(type);
                    var result  = BuildApiListHtml(typeapi);
                    context.Response.Clear();
                    context.Response.ContentType = "text/html";
                    context.Response.Write(result);
                }
                // 输出api接口清单
                else if (methodNameLower == "apis")
                {
                    var typeapi = GetTypeApi(type);
                    context.Response.Clear();
                    WriteResult(context, typeapi, ResponseType.JSON);
                }
                // 输出js/jquery/ext脚本
                else
                {
                    string        nameSpace = GetJsNamespace(type, args);
                    string        className = GetJsClassName(type, args);
                    StringBuilder result    = GetJs(type, nameSpace, className, cacheDuration, methodNameLower);
                    WriteResult(context, result, ResponseType.JavaScript);
                }
            }

            // 处理缓存
            CacheHelper.SetCachePolicy(context, cacheDuration);
            return(true);
        }