private async Task ExecuteAction(RouteMatch match, FilterContext context, TwinoController controller, ActionDescriptor descriptor, HttpResponse response) { if (match.Route.IsAsyncMethod) { Task <IActionResult> task = (Task <IActionResult>)match.Route.ActionType.Invoke(controller, descriptor.Parameters.Select(x => x.Value).ToArray()); await task; await CompleteActionExecution(match, context, response, controller, descriptor, task.Result); } else { TaskCompletionSource <bool> source = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); ThreadPool.QueueUserWorkItem(async t => { try { IActionResult ar = (IActionResult)match.Route.ActionType.Invoke(controller, descriptor.Parameters.Select(x => x.Value).ToArray()); await CompleteActionExecution(match, context, response, controller, descriptor, ar); source.SetResult(true); } catch (Exception e) { source.SetException(e.InnerException ?? e); } }); await source.Task; } }
public async Task FindRoutes(string method, string path, string aResult) { TwinoMvc mvc = new TwinoMvc(); mvc.Init(); mvc.CreateRoutes(Assembly.GetExecutingAssembly()); HttpRequest request = new HttpRequest(); request.Method = method; request.Path = path; HttpResponse response = new HttpResponse(); RouteMatch match = mvc.RouteFinder.Find(mvc.Routes, request); Assert.NotNull(match); TwinoController controller = await mvc.ControllerFactory.CreateInstance(mvc, match.Route.ControllerType, request, response, mvc.Services.CreateScope()); var parameters = MvcConnectionHandler.FillParameters(request, match).Select(x => x.Value).ToArray(); Task <IActionResult> task = (Task <IActionResult>)match.Route.ActionType.Invoke(controller, parameters); IActionResult result = task.Result; string url = Encoding.UTF8.GetString(((MemoryStream)result.Stream).ToArray()); url.Should().Be(aResult); }
/// <summary> /// Completes action execution, calls after actions and writes response /// </summary> private async Task CompleteActionExecution(RouteMatch match, FilterContext context, HttpResponse response, TwinoController controller, ActionDescriptor descriptor, IActionResult actionResult) { if (actionResult == null) { return; } //IActionResult actionResult = match.Route.ActionType.Invoke(controller, descriptor.Parameters.Select(x => x.Value).ToArray()) as IActionResult; context.Result = actionResult; if (match.Route.HasActionExecutedFilter) { //find controller filters IActionExecutedFilter[] filters = (IActionExecutedFilter[])match.Route.ActionType.GetCustomAttributes(typeof(IActionExecutedFilter), true); //call AfterCreated methods of controller attributes foreach (IActionExecutedFilter filter in filters) { await filter.OnExecuted(controller, descriptor, actionResult, context); } } if (match.Route.HasControllerExecutedFilter) { //find controller filters IActionExecutedFilter[] filters = (IActionExecutedFilter[])match.Route.ControllerType.GetCustomAttributes(typeof(IActionExecutedFilter), true); //call AfterCreated methods of controller attributes foreach (IActionExecutedFilter filter in filters) { await filter.OnExecuted(controller, descriptor, actionResult, context); } } await controller.CallActionExecuted(descriptor, context, actionResult); WriteResponse(response, actionResult); }
/// <summary> /// Handles the request in MVC pattern /// </summary> private async Task RequestMvc(ITwinoServer server, HttpRequest request, HttpResponse response, IContainerScope scope) { //find file route if (Mvc.FileRoutes.Count > 0) { IActionResult fileResult = Mvc.RouteFinder.FindFile(Mvc.FileRoutes, request); if (fileResult != null) { response.SuppressContentEncoding = true; WriteResponse(response, fileResult); return; } } //find controller route RouteMatch match = Mvc.RouteFinder.Find(Mvc.Routes, request); if (match?.Route == null) { WriteResponse(response, Mvc.NotFoundResult); return; } //read user token ClaimsPrincipal user = null; if (Mvc.ClaimsPrincipalValidator != null) { user = Mvc.ClaimsPrincipalValidator.Get(request); } FilterContext context = new FilterContext { Server = server, Request = request, Response = response, Result = null, User = user }; if (!CheckControllerAuthority(match, context, response)) { return; } if (!await ExecuteBeforeControllerFilters(match, context, response)) { return; } TwinoController controller = await Mvc.ControllerFactory.CreateInstance(Mvc, match.Route.ControllerType, request, response, scope); if (controller == null) { WriteResponse(response, Mvc.NotFoundResult); return; } controller.User = user; if (!await ExecuteAfterControllerFilters(match, context, response, controller)) { return; } //fill action descriptor ActionDescriptor descriptor = new ActionDescriptor { Controller = controller, Action = match.Route.ActionType, Parameters = FillParameters(request, match) }; if (!CheckActionAuthority(match, context, response, descriptor)) { return; } if (!await CheckActionExecutingFilters(match, context, response, controller, descriptor)) { return; } await controller.CallActionExecuting(descriptor, context); if (context.Result != null) { WriteResponse(response, context.Result); return; } await ExecuteAction(match, context, controller, descriptor, response); }