using System; using System.Web.Mvc; using System.Web.Routing; using MvcContrib; using MvcContrib.Filters; namespace MvcContrib { /// /// SubController base class for subcontrollers. SubControllers can be infinitely nested. /// [SubControllerActionToViewData] public class SubController : Controller, ISubController { public virtual Action GetResult(ControllerBase parentController) { RequestContext requestContext = GetNewRequestContextFromController(parentController); return () => Execute(requestContext); } /// /// Gets new RequestContext using objects from parent controller. This ensures subcontrollers have their own state that doesn't conflict with the parent. /// ///Parent controller ///RequestContext public RequestContext GetNewRequestContextFromController(ControllerBase parentController) { RouteData parentRouteData = parentController.ControllerContext.RouteData; var routeData = new RouteData(parentRouteData.Route, parentRouteData.RouteHandler); string controllerName = GetControllerName(); routeData.Values["controller"] = controllerName; routeData.Values["action"] = controllerName; return new RequestContext(parentController.ControllerContext.HttpContext, routeData); } /// /// Gets the name from the type by trimming "controller" and "subcontroller" from the type name. The subcontroller action must match the controller name. /// /// public string GetControllerName() { string typeNameLowered = GetType().Name.ToLowerInvariant(); int index = typeNameLowered.IndexOf("subcontroller"); if(index == -1) { index = typeNameLowered.IndexOf("controller"); } if(index == -1) { return typeNameLowered; } return typeNameLowered.Substring(0, index); } } /// /// SubController with generic Model property. /// /// public class SubController : SubController, ISubController { public virtual T Model { get; set; } } }