public static HttpResponseMessage InvokeAction( HttpRoute matchedRoute, ICollection <Type> controllerTypes, IDependencyResolver resolver, IControllerFactory controllerFactory) { #region Please modify the following code to pass the test /* * In this test, you have to create the controller from its name rather * than its type. So we introduced a new interface called IControllerFactory. * It will create controller directly by its name with the help of * controller type collection returned by IHttpControllerTypeResolver and * IDependencyResolver. */ HttpController controller = null; try { controller = controllerFactory.CreateController(matchedRoute.ControllerName, controllerTypes, resolver); } catch { return(new HttpResponseMessage(HttpStatusCode.InternalServerError)); } if (controller == null) { return(new HttpResponseMessage(HttpStatusCode.InternalServerError)); } return(InvokeActionInternal(new ActionDescriptor(controller, matchedRoute.ActionName, matchedRoute.MethodConstraint))); #endregion }
/* * In previous practice. We refactored InvokeAction method. Now we have * renamed its name from "InvokeAction" to "InvokeActionInternal". The * InvokeAction method will no longer accept ActionDescriptor instance. * Instead, it will create the ActionDescriptor instance from a matching * route and an IDependencyResolver instance. * * The matched route contains the type of the controller, the name of the * action and the method constraint. It should use a resolver to create * controller from its type. */ public static HttpResponseMessage InvokeAction(HttpRoute matchedRoute, IDependencyResolver resolver) { HttpController controller = (HttpController)resolver.GetService(matchedRoute.ControllerType); if (controller == null) { return(new HttpResponseMessage(HttpStatusCode.InternalServerError)); } return(InvokeActionInternal(new ActionDescriptor(controller, matchedRoute.ActionName, matchedRoute.MethodConstraint))); }
static MethodInfo GetAction(ActionDescriptor actionDescriptor) { HttpController controller = actionDescriptor.Controller; string actionName = actionDescriptor.ActionName; Type controllerType = controller.GetType(); const BindingFlags controllerActionBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase; return(controllerType.GetMethod(actionName, controllerActionBindingFlags)); }
/* * Now we will create a framework just like the ASP.NET WebApi. We called * it LocalApi. The core part of the Api framework is generating response. * And the most important type for generating response is the HttpController. * In this practice, we try invoking the specified action of the controller * to generate a response. * * The class to invoke controller action is called a ControllerActionInvoker, * and the entry point is called InvokeAction. It accepts an actionDescriptor * which contains the instance of the controller (currently we have no idea * where it comes from), the name of the action to invoke. For simplicity, * we assume that all actions contains no parameter. */ public static HttpResponseMessage InvokeAction(ActionDescriptor actionDescriptor) { HttpController controller = actionDescriptor.Controller; var actionName = actionDescriptor.ActionName; Type type = controller.GetType(); MethodInfo methodInfo = type .GetMethod(actionName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); if (methodInfo == null) { return(new HttpResponseMessage(HttpStatusCode.NotFound)); } try { return((HttpResponseMessage)methodInfo.Invoke(controller, new object[] {})); } catch (TargetInvocationException) { return(new HttpResponseMessage(HttpStatusCode.InternalServerError)); } }
public ActionDescriptor(HttpController controller, string actionName, HttpMethod methodConstraint) { Controller = controller; ActionName = actionName; MethodConstraint = methodConstraint; }