protected void AssertParamParse(string paramKey, string[] paramValues, Type type, object expectedValue, bool hasDefaultValue = false, object defaultValue = null, string overrideParamName = null) { IModelBinder binder = GetModelBinder(); HttpRequest request = GetHttpRequest(paramKey, paramValues); ActionContext action = GetActionContext(binder, type, hasDefaultValue, defaultValue, overrideParamName); object[] parameters = binder.GetParameterValues(request, action); Assert.Equal(1, parameters.Length); Assert.Equal(expectedValue, parameters[0]); }
/// <summary> /// Invokes the specified <see cref="ActionContext"/>. /// </summary> /// <param name="httpCtx">The HTTP context, set by the middleware.</param> /// <param name="actionCtx">The action context.</param> /// <param name="logger">Logger to use, can be null</param> /// <returns></returns> public virtual async Task Invoke(HttpContext httpCtx, ActionContext actionCtx, ILogger logger = null) { logger?.LogInformation("Checking filters"); ApiFilterRunResult filterResult = await RunFiltersAndCheckIfShouldContinue(httpCtx, actionCtx); logger?.LogInformation($"Checking filters completed, can invoke: {filterResult.ShouldContinue}"); if (!filterResult.ShouldContinue) { int failedStatusCode = 0; if (filterResult.SetResponseCode.HasValue) { failedStatusCode = filterResult.SetResponseCode.Value; } else { bool isAuthenticated = httpCtx?.User?.Identity?.IsAuthenticated ?? false; if (isAuthenticated) { failedStatusCode = 403; } else { failedStatusCode = 401; } } httpCtx.Response.StatusCode = failedStatusCode; await httpCtx.Response.WriteAsync(filterResult.SetResponseMessage ?? "request rejected"); logger?.LogInformation($"returning response with status code: {failedStatusCode}"); return; } logger?.LogInformation($"Building controller: {actionCtx.ParentController}"); LiteController ctrl = _controllerBuilder.Build(actionCtx.ParentController, httpCtx); object[] paramValues = _modelBinder.GetParameterValues(httpCtx.Request, actionCtx); logger?.LogInformation($"Building controller succeeded: {actionCtx.ParentController}"); logger?.LogInformation($"Invoking action: {actionCtx}"); object result = null; bool isVoid = true; if (actionCtx.Method.ReturnType == typeof(void)) { actionCtx.Method.Invoke(ctrl, paramValues); } else if (actionCtx.Method.ReturnType == typeof(Task)) { var task = (actionCtx.Method.Invoke(ctrl, paramValues) as Task); await task; } else if (actionCtx.Method.ReturnType.IsConstructedGenericType && actionCtx.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) { isVoid = false; var task = (dynamic)(actionCtx.Method.Invoke(ctrl, paramValues)); result = await task; } else { isVoid = false; result = actionCtx.Method.Invoke(ctrl, paramValues); } int?overridenResponseCode = httpCtx.GetResponseStatusCode(); if (overridenResponseCode.HasValue) { httpCtx.Response.StatusCode = overridenResponseCode.Value; } else { int statusCode = 405; // method not allowed switch (httpCtx.Request.Method.ToUpper()) { case "GET": statusCode = 200; break; case "POST": statusCode = 201; break; case "PUT": statusCode = 201; break; case "DELETE": statusCode = 204; break; } httpCtx.Response.StatusCode = statusCode; } httpCtx.Response.Headers.Add("X-Powered-By-Middleware", "LiteApi"); var additionalHeaders = httpCtx.GetResponseHeaders(true); if (additionalHeaders != null) { foreach (var header in additionalHeaders) { httpCtx.Response.Headers.Add(header.Key, header.Value); } } if (isVoid) { logger?.LogInformation("Not serializing result from invoked action, action is void or void task"); } else { logger?.LogInformation("Serializing result from invoked action"); if (actionCtx.IsReturningLiteActionResult) { await(result as ILiteActionResult).WriteResponse(httpCtx, actionCtx); } else { httpCtx.Response.ContentType = "application/json"; await httpCtx.Response.WriteAsync(_jsonSerializer.Serialize(result)); } } }