/// <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); }