Пример #1
0
        /// <summary>
        /// Handles the actual method invocation, once a method has been selected
        /// </summary>
        /// <returns>The awaitable task.</returns>
        /// <param name="context">The execution context.</param>
        /// <param name="method">The method to invoke.</param>
        /// <param name="controller">The controller instance to use.</param>
        /// <param name="urlmatch">The parent url match</param>
        private async Task HandleWithMethod(IHttpContext context, MethodEntry method, Controller controller, Dictionary <string, string> urlmatch)
        {
            // Make sure dependencies are met
            context.Request.RequireHandler(controller.GetType().GetCustomAttributes <RequireHandlerAttribute>());
            context.Request.RequireHandler(method.Method.GetCustomAttributes <RequireHandlerAttribute>());

            // Apply each argument in turn
            var values      = new object[method.ArgumentCount];
            var hasreadbody = false;

            foreach (var m in urlmatch)
            {
                context.Request.RequestState[m.Key] = m.Value;
            }

            for (var ix = 0; ix < values.Length; ix++)
            {
                var            e = method.Parameters[ix];
                string         val;
                IMultipartItem file;

                if (typeof(IHttpContext).IsAssignableFrom(e.Parameter.ParameterType))
                {
                    values[ix] = context;
                }
                else if (typeof(IHttpRequest).IsAssignableFrom(e.Parameter.ParameterType))
                {
                    values[ix] = context.Request;
                }
                else if (typeof(IHttpResponse).IsAssignableFrom(e.Parameter.ParameterType))
                {
                    values[ix] = context.Response;
                }
                else if (e.Source.HasFlag(ParameterSource.Url) && urlmatch != null && urlmatch.TryGetValue(e.Name, out val))
                {
                    ApplyArgument(method.Method, e, val, values);
                }
                else if (e.Source.HasFlag(ParameterSource.Header) && context.Request.Headers.TryGetValue(e.Name, out val))
                {
                    ApplyArgument(method.Method, e, val, values);
                }
                else if (e.Source.HasFlag(ParameterSource.Form) && context.Request.Form.TryGetValue(e.Name, out val))
                {
                    ApplyArgument(method.Method, e, val, values);
                }
                else if (e.Source.HasFlag(ParameterSource.Form) && ((file = context.Request.Files.FirstOrDefault(x => string.Equals(x.Name, e.Name, StringComparison.OrdinalIgnoreCase))) != null))
                {
                    ApplyArgument(method.Method, e, await RequestUtility.ReadAllAsStringAsync(file.Data, RequestUtility.GetEncodingForContentType(file.Headers["Content-Type"]), context.Request.TimeoutCancellationToken), values);
                }
                else if (e.Source.HasFlag(ParameterSource.Query) && context.Request.QueryString.TryGetValue(e.Name, out val))
                {
                    ApplyArgument(method.Method, e, val, values);
                }
                else if (e.Source.HasFlag(ParameterSource.Body) && !hasreadbody && RequestUtility.IsJsonRequest(context.Request.ContentType))
                {
                    // We can have at most one body param
                    hasreadbody = true;
                    var str = await RequestUtility.ReadAllAsStringAsync(context.Request.Body, RequestUtility.GetEncodingForContentType(context.Request.ContentType), context.Request.TimeoutCancellationToken);

                    ApplyArgument(method.Method, e, str, values);
                }
                else if (e.Required)
                {
                    throw new HttpException(HttpStatusCode.BadRequest, $"Missing mandatory parameter {e.Name}");
                }
                else if (e.Parameter.HasDefaultValue)
                {
                    values[e.ArgumentIndex] = e.Parameter.DefaultValue;
                }
                else
                {
                    values[e.ArgumentIndex] = e.Parameter.ParameterType.IsValueType ? Activator.CreateInstance(e.Parameter.ParameterType) : null;
                }

                // Provide the bound variables to the processing module
                if (!e.IsContextParameter)
                {
                    context.Request.RequestState[e.Name] = values[e.ArgumentIndex];
                }
            }

            var res = method.Method.Invoke(controller, values);

            if (res == null)
            {
                return;
            }

            if (res is IResult)
            {
                await((IResult)res).Execute(context);
            }
            else if (res is Task <IResult> )
            {
                res = await(Task <IResult>) res;
                if (res as IResult != null)
                {
                    await((IResult)res).Execute(context);
                }
            }
            else if (res is Task)
            {
                await(Task) res;
            }
        }