public virtual async void Run(HttpContext context) { context.Features.Get <IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = null; var requestStart = DateTime.Now; DateTime requestEnd; TimeSpan tspan; var requestType = ""; var path = cleanPath(context.Request.Path.ToString()); var paths = path.Split('/').ToArray(); var extension = ""; //get request file extension (if exists) if (path.IndexOf(".") >= 0) { for (int x = path.Length - 1; x >= 0; x += -1) { if (path.Substring(x, 1) == ".") { extension = path.Substring(x + 1); return; } } } server.requestCount += 1; if (server.environment == Server.enumEnvironment.development) { Console.WriteLine("--------------------------------------------"); Console.WriteLine("{0} GET {1}", DateTime.Now.ToString("hh:mm:ss"), path); //optionally, wipe Scaffold cache to enable developer updates to html files when server is running server.Scaffold = new Dictionary <string, SerializedScaffold>(); } //get form files (if any exist) IFormCollection form = null; if (context.Request.ContentType != null) { if (context.Request.ContentType.IndexOf("multipart/form-data") >= 0) { form = context.Request.Form; } } byte[] bytes = new byte[0]; string data = ""; int dataType = 0; //0 = ajax, 1 = HTML form post, 2 = multi-part form (with file uploads) //figure out what kind of data was sent with the request if (form == null && context.Request.Body.CanRead) { //get POST data from request using (MemoryStream ms = new MemoryStream()) { context.Request.Body.CopyTo(ms); bytes = ms.ToArray(); } data = Encoding.UTF8.GetString(bytes, 0, bytes.Length).Trim(); } else { //form files exist dataType = 2; } if (paths.Length > 1) { if (paths[0] == "api") { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //run a web service via ajax (e.g. /api/namespace/class/function) ////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (cleanNamespace(paths)) { //execute web service requestType = "service"; //get parameters from request body, including page id var parms = new Dictionary <string, string>(); object[] paramVals; var param = ""; if (data.Length > 0) { if (data.IndexOf("Content-Disposition") > 0) { //multi-part file upload dataType = 2; } else if (data.IndexOf("{") >= 0 && data.IndexOf("}") > 0 && data.IndexOf(":") > 0) { //get method parameters from POST S.ajax.post() Dictionary <string, object> attr = JsonConvert.DeserializeObject <Dictionary <string, object> >(data); foreach (KeyValuePair <string, object> item in attr) { parms.Add(item.Key.ToLower(), item.Value.ToString()); } } else if (data.IndexOf("=") >= 0) { //HTML form POST data dataType = 1; } } else { //get method parameters from query string foreach (var key in context.Request.Query.Keys) { parms.Add(key.ToLower(), context.Request.Query[key].ToString()); } } //start building Web API response (find method to execute & return results) var S = new Core(server, context); //load service class from URL path string className = S.Server.nameSpace + ".Services." + paths[1]; string methodName = paths[2]; if (paths.Length == 4) { className += "." + paths[2]; methodName = paths[3]; } var routes = new global::Routes(S); var service = routes.FromServiceRoutes(className); if (service == null) { try { Type stype = Type.GetType(className); service = (Service)Activator.CreateInstance(stype, new object[] { S }); } catch (Exception) { } } //check if service class was found if (service == null) { S.Response.ContentType = "text/html"; context.Response.WriteAsync("no service found"); S.Unload(); return; } if (dataType == 1) { //parse HTML form POST data and send to new Service instance string[] items = S.Server.UrlDecode(data).Split('&'); string[] item; for (var x = 0; x < items.Length; x++) { item = items[x].Split('='); service.Form.Add(item[0], item[1]); } } else if (dataType == 2) { //send multi-part file upload data to new Service instance service.Files = form.Files; } //execute method from new Service instance Type type = Type.GetType(className); MethodInfo method = type.GetMethod(methodName); //try to cast params to correct types ParameterInfo[] methodParams = method.GetParameters(); paramVals = new object[methodParams.Length]; for (var x = 0; x < methodParams.Length; x++) { //find correct key/value pair param = ""; foreach (var item in parms) { if (item.Key == methodParams[x].Name.ToLower()) { param = item.Value; break; } } if (param == "") { //set default value for empty parameter var t = methodParams[x].ParameterType; if (t == typeof(Int32)) { param = "0"; } } //cast params to correct (supported) types if (methodParams[x].ParameterType.Name != "String") { var i = 0; if (int.TryParse(param, out i) == true) { if (methodParams[x].ParameterType.IsEnum == true) { //enum paramVals[x] = Enum.Parse(methodParams[x].ParameterType, param); } else { //int paramVals[x] = Convert.ChangeType(i, methodParams[x].ParameterType); } } else if (methodParams[x].ParameterType.FullName.Contains("DateTime")) { if (param == "") { paramVals[x] = null; } else { try { paramVals[x] = DateTime.Parse(param); } catch (Exception) { } } } else if (methodParams[x].ParameterType.IsArray) { var arr = param.Replace("[", "").Replace("]", "").Replace("\r", "").Replace("\n", "").Split(",").Select(a => { return(a.Trim()); }).ToList(); if (methodParams[x].ParameterType.FullName == "System.Int32[]") { paramVals[x] = arr.Select(a => { return(int.Parse(a)); }).ToArray(); } else { paramVals[x] = Convert.ChangeType(arr, methodParams[x].ParameterType); } } else if (methodParams[x].ParameterType.Name.IndexOf("Dictionary") == 0) { paramVals[x] = (Dictionary <string, string>)S.Util.Serializer.ReadObject(param, typeof(Dictionary <string, string>)); } else { paramVals[x] = Convert.ChangeType(param, methodParams[x].ParameterType); } } else { //string paramVals[x] = param; } } object result = null; try { result = method.Invoke(service, paramVals); } catch (Exception ex) { if (server.environment == Server.enumEnvironment.development) { Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } throw ex; } //finally, unload the Datasilk Core: //close SQL connection, save User info, etc (before sending response) S.Unload(); context.Response.ContentType = "text/json"; if (result != null) { context.Response.WriteAsync((string)result); } else { context.Response.WriteAsync("{\"error\":\"no content returned\"}"); } } } } if (requestType == "" && extension == "") { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //page request (initialize client-side application) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// requestType = "page"; var S = new Core(server, context); //create instance of Page class based on request URL path var html = ""; var newpaths = path.Split('?', 2)[0].Split('/'); var routes = new global::Routes(S); var page = routes.FromPageRoutes(newpaths[0].ToLower()); if (page == null) { //page is not part of any known routes, try getting page class manually Type type = Type.GetType((S.Server.nameSpace + ".Pages." + (newpaths[0] == "" ? "Login" : S.Util.Str.Capitalize(newpaths[0].Replace("-", " ")).Replace(" ", "")))); page = (Page)Activator.CreateInstance(type, new object[] { S }); } if (page != null) { //render page if (form != null) { page.Files = form.Files; } try { html = page.Render(newpaths); } catch (Exception ex) { Console.WriteLine(ex.Message + "\n" + ex.StackTrace); throw ex; } } else { //show 404 error page = new Page(S); html = page.Error404(); } //unload Datasilk Core page = null; S.Unload(); //send response back to client S.Response.ContentType = "text/html"; await S.Response.WriteAsync(html); } if (server.environment == Server.enumEnvironment.development) { requestEnd = DateTime.Now; tspan = requestEnd - requestStart; server.requestTime += (tspan.Seconds); Console.WriteLine("END REQUEST {0} ms, {1} {2}", tspan.Milliseconds, path, requestType); Console.WriteLine(""); } }