Beispiel #1
0
        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();
        }