public static JSBFunction CreateLinkFunction(string baseApiPath, string controller, MethodInfo info, bool useName) { List <ParameterInfo> paras = info.GetParameters().Where(x => !BodyAttribute.HasAttribute(x)).ToList(); ParameterInfo bodyParameter = info.GetParameters().FirstOrDefault(x => BodyAttribute.HasAttribute(x)); string bodyParaName = (bodyParameter != null) ? bodyParameter.Name : ""; BodyAttribute bodyAttr = null; if (bodyParameter != null) { bodyAttr = BodyAttribute.GetAttribute(bodyParameter); } List <string> stringParas = paras.Select(x => x.Name).ToList(); MethodDescriptorAttribute descriptor = MethodDescriptorAttribute.GetDescriptor(info); if (descriptor != null) { //stringParas = new List<string>(); foreach (string para in descriptor.Parameters) { if (!stringParas.Contains(para)) { stringParas.Add(para); } } if (descriptor.HasPostParameter) { bodyParaName = descriptor.PostParameter; } } if (RequiresTokenAttribute.HasAttribute(info)) { stringParas.Add("t"); } JSBuilder code = new JSBuilder(); StringBuilder paraString = new StringBuilder(); for (int i = 0; i < stringParas.Count; i++) { if (i == 0) { paraString.Append("?"); } else { paraString.Append("&"); } paraString.Append(stringParas[i] + "=' + " + stringParas[i] + " + '"); } if (RequiresTokenAttribute.HasAttribute(info)) { code.AddCode("if(!t) t = Sync.Token;"); } string baseUrlPrepend = ((APIBaseUrl != "") ? $"{APIBaseUrl}/" : ""); if (!string.IsNullOrEmpty(bodyParaName)) { if (bodyAttr != null && bodyAttr.BodyType == BodyType.Raw) { if (descriptor != null && descriptor.ResponseType == BodyType.Raw) { code.AddCode($"SyncPostRawRaw('{baseUrlPrepend + controller}/{info.Name}{paraString.ToString()}', {bodyParaName}, callback);"); } else { code.AddCode($"SyncPostRawJson('{baseUrlPrepend + controller}/{info.Name}{paraString.ToString()}', {bodyParaName}, callback);"); } } else { if (descriptor != null && descriptor.ResponseType == BodyType.Raw) { code.AddCode($"SyncPostJsonRaw('{baseUrlPrepend + controller}/{info.Name}{paraString.ToString()}', {"JSON.stringify(" + bodyParaName + ")"}, callback);"); } else { code.AddCode($"SyncPostJson('{baseUrlPrepend + controller}/{info.Name}{paraString.ToString()}', {"JSON.stringify(" + bodyParaName + ")"}, callback);"); } } } else { if (descriptor != null && descriptor.ResponseType == BodyType.Raw) { code.AddCode($"SyncGetRaw('{baseUrlPrepend + controller}/{info.Name}{paraString.ToString()}', callback);"); } else { code.AddCode($"SyncGetJson('{baseUrlPrepend + controller}/{info.Name}{paraString.ToString()}', callback);"); } } if (!string.IsNullOrEmpty(bodyParaName)) { if (stringParas.LastOrDefault() == "t") { stringParas.Insert(stringParas.Count - 1, bodyParaName); } else { stringParas.Add(bodyParaName); } } if (stringParas.LastOrDefault() == "t") { stringParas.Insert(stringParas.Count - 1, "callback"); } else { stringParas.Add("callback"); } JSBFunction func = new JSBFunction(((useName) ? info.Name : null), code, stringParas.ToArray()); return(func); }
public string Sync() { bool isUpdate = false; if (Request.Parameters.ContainsKey("update")) { bool.TryParse(Request.Parameters["update"], out isUpdate); } if ((Authenticated && !GeneratedSyncAuthorized.ContainsKey(AuthenticationLevel)) || (!Authenticated && string.IsNullOrEmpty(GeneratedSync))) { JSBObject jsControllers = new JSBObject(); foreach (ControllerRoute tkv in GetControllers()) { string controllerPath = tkv.Path; //System.Console.WriteLine(controllerPath); ControllerDescriptor template = tkv.Controller; JSBObject jsController = new JSBObject(); foreach (KeyValuePair <string, CallDescriptor> mkv in template.Calls.Where(x => !IgnoreSyncAttribute.HasAttribute(x.Value.Info))) { MethodInfo method = mkv.Value.Info; RequiresTokenAttribute requiresVerify = RequiresTokenAttribute.GetAttribute(method); if (requiresVerify == null || (requiresVerify != null && Authenticated && requiresVerify.LevelRequired <= AuthenticationLevel)) { string typeName = template.ControllerType.Name; string controllerName = typeName.Replace("Controller", "").Replace("`1", ""); JSBFunction func = CreateLinkFunction(APIBaseUrl, controllerPath, method, false); if (!jsController.Properties.ContainsKey(method.Name)) { jsController.AddFunction(method.Name, func); } } } if (jsController.Properties.Any()) { jsControllers.AddObject(template.ControllerType.Name.Replace("Controller", "").Replace("`1", ""), jsController); } } JSBuilder js = new JSBuilder().AssignVariable("Sync", jsControllers); if (!isUpdate) { js.DefineFunction("SyncGetJson", @" var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function () { if (ajax.readyState == 4 && ajax.status == 200) /*callback(JSON.parse(ajax.responseText))*/ callback(ResolveReferences(ajax.responseText)) }; ajax.open('GET', url, true); ajax.setRequestHeader('Accept', 'application/json'); ajax.send(); ", "url", "callback") .DefineFunction("SyncPostJson", @" var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function () { if (ajax.readyState == 4 && ajax.status == 200) { /*callback(JSON.parse(ajax.responseText))*/ callback(ResolveReferences(ajax.responseText)) } }; ajax.open('POST', url, true); ajax.send(data); ", "url", "data", "callback") .DefineFunction("SyncGetRaw", @" var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function () { if (ajax.readyState == 4 && ajax.status == 200) /*callback(JSON.parse(ajax.responseText))*/ callback(ajax.responseText) }; ajax.open('GET', url, true); ajax.setRequestHeader('Accept', 'application/json'); ajax.send(); ", "url", "callback") .DefineFunction("SyncPostJsonRaw", @" var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function () { if (ajax.readyState == 4 && ajax.status == 200) { callback(ajax.responseText) } }; ajax.open('POST', url, true); ajax.send(data); ", "url", "data", "callback") .DefineFunction("SyncPostRawRaw", @" var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function () { if (ajax.readyState == 4 && ajax.status == 200) { callback(ajax.responseText) } }; ajax.open('POST', url, true); ajax.send(data); ", "url", "data", "callback") .DefineFunction("SyncPostRawJson", @" var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function () { if (ajax.readyState == 4 && ajax.status == 200) { callback(ResolveReferences(ajax.responseText)) } }; ajax.open('POST', url, true); ajax.send(data); ", "url", "data", "callback") .DefineFunction("ResolveReferences", @" if (typeof json === 'string') json = JSON.parse(json); var byid = {}; var refs = []; json = (function recurse(obj, prop, parent) { if (typeof obj !== 'object' || !obj) return obj; if (Object.prototype.toString.call(obj) === '[object Array]') { for (var i = 0; i < obj.length; i++) if (typeof obj[i] !== 'object' || !obj[i]) continue; else if (""$ref "" in obj[i]) obj[i] = recurse(obj[i], i, obj); else obj[i] = recurse(obj[i], prop, obj); return obj; } if (""$ref"" in obj) { var ref = obj.$ref; if (ref in byid) return byid[ref]; refs.push([parent, prop, ref]); return; } else if (""$id"" in obj) { var id = obj.$id; delete obj.$id; if (""$values"" in obj) obj = obj.$values.map(recurse); else for (var prop in obj) obj[prop] = recurse(obj[prop], prop, obj); byid[id] = obj; } return obj; })(json); for (var i = 0; i<refs.length; i++) { var ref = refs[i]; ref[0][ref[1]] = byid[ref[2]]; } return json;", "json"); } if (Authenticated) { GeneratedSyncAuthorized.Add(AuthenticationLevel, js.BuildCode()); } else { GeneratedSync = js.BuildCode(); } } Request.Response.ContentType = "application/javascript"; string addition = ""; if (Authenticated) { addition += $"Sync.Token = '{Token.UrlEncode()}';"; } if (isUpdate) { return(((Authenticated) ? GeneratedSyncAuthorized[AuthenticationLevel] : GeneratedSync) + "\n" + addition); } else { return(((Authenticated) ? "var " + GeneratedSyncAuthorized[AuthenticationLevel] : "var " + GeneratedSync) + "\n" + addition); } }