protected async Task Dispatch(HttpContext context, MethodInfo method, params object[] list) { Context = context; _nestedParams = await context.SetupNestedParams(); if (RouteVars != null) { if (_nestedParams.ExtraParams == null) { _nestedParams.ExtraParams = new NestedDictionary(); } foreach (var pair in RouteVars) { _nestedParams.ExtraParams.Set(pair.Key, pair.Value); } } await BeforeDispatch.Invoke(this); var ca = new ControllerArgs(); await BeforeAction.Invoke(this, ca); if (ca.Cancel) { return; } var mParams = method.GetParameters(); // If no parameters are passed, try to infer them. if (list.Length == 0 && mParams.Length > 0) { var newList = new object[mParams.Length]; var i = 0; foreach (var mParam in mParams) { if (Params.ContainsKey(mParam.Name)) { newList[i] = Params.Get(mParam.ParameterType, mParam.Name); } else { newList[i] = Type.Missing; } i++; } list = newList; } else if (list.Length < mParams.Length) { var newList = new object[mParams.Length]; for (var i = 0; i < mParams.Length; i++) { newList[i] = i > list.Length - 1 ? Type.Missing : list[i]; } list = newList; } var response = await Utils.ExtractRefTask(method.Invoke(this, list)); if (response is HttpResponse hr) { Response.ContentType = hr.ContentType; } if (string.IsNullOrWhiteSpace(Response.ContentType)) { Response.ContentType = "text/html; charset=utf-8"; } await AfterAction.Invoke(this); if (SessionAvailable) { await Session.CommitAsync(); } object finalResponse; if (response is HttpResponse http) { foreach (var pair in http.Headers) { Response.Headers[pair.Key] = pair.Value; } Response.StatusCode = http.StatusCode; finalResponse = http.Body; } else { finalResponse = response; } switch (finalResponse) { case Stream stream: if (!stream.CanRead) { throw new ArgumentException("Can't read HttpResponse stream"); } if (stream.CanSeek) { stream.Seek(0, SeekOrigin.Begin); } await stream.CopyToAsync(Response.Body, 51200); // Copy in 50KB chunks stream.Dispose(); break; case string str: await Response.WriteAsync(str); break; case byte[] bytea: Response.Body = new MemoryStream(bytea); break; case null: // Do nothing break; default: if (IsJsonController) { var str = JsonSerializer.Serialize(finalResponse, JsonSettings); await Response.WriteAsync(str); } else { await CleanUp(); throw new Exception( $"Unknown response type from controller: {response.GetType().FullName} (in {GetType().FullName})"); } break; } await CleanUp(); }