/// <summary>
        /// Returns a RouteDefinition object based on the current renderModel
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="publishedContentRequest"></param>
        /// <returns></returns>
        internal virtual RouteDefinition GetUmbracoRouteDefinition(RequestContext requestContext, PublishedContentRequest publishedContentRequest)
        {
            var defaultControllerName = ControllerExtensions.GetControllerName <RenderMvcController>();
            //creates the default route definition which maps to the 'UmbracoController' controller
            var def = new RouteDefinition
            {
                ControllerName          = defaultControllerName,
                Controller              = new RenderMvcController(),
                PublishedContentRequest = publishedContentRequest,
                ActionName              = ((Route)requestContext.RouteData.Route).Defaults["action"].ToString(),
                HasHijackedRoute        = false
            };

            //check if there's a custom controller assigned, base on the document type alias.
            var controller = _controllerFactory.CreateController(requestContext, publishedContentRequest.PublishedContent.DocumentTypeAlias);


            //check if that controller exists
            if (controller != null)
            {
                //ensure the controller is of type 'RenderMvcController'
                if (controller is RenderMvcController)
                {
                    //set the controller and name to the custom one
                    def.Controller     = (ControllerBase)controller;
                    def.ControllerName = ControllerExtensions.GetControllerName(controller.GetType());
                    if (def.ControllerName != defaultControllerName)
                    {
                        def.HasHijackedRoute = true;
                    }
                }
                else
                {
                    LogHelper.Warn <RenderRouteHandler>("The current Document Type {0} matches a locally declared controller of type {1}. Custom Controllers for Umbraco routing must inherit from '{2}'.", publishedContentRequest.PublishedContent.DocumentTypeAlias, controller.GetType().FullName, typeof(RenderMvcController).FullName);
                    //exit as we cannnot route to the custom controller, just route to the standard one.
                    return(def);
                }

                //check that a template is defined), if it doesn't and there is a hijacked route it will just route
                // to the index Action
                if (publishedContentRequest.HasTemplate)
                {
                    //check if the custom controller has an action with the same name as the template name (we convert ToUmbracoAlias since the template name might have invalid chars).
                    //NOTE: This also means that all custom actions MUST be PascalCase.. but that should be standard.
                    var templateName = publishedContentRequest.Template.Alias.Split('.')[0].ToUmbracoAlias(StringAliasCaseType.PascalCase);
                    def.ActionName = templateName;
                }
            }


            return(def);
        }
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            var umbracoContext = GetUmbracoContext(requestContext);

            var found = FindContent(requestContext, umbracoContext);

            if (found == null)
            {
                return(new NotFoundHandler());
            }

            umbracoContext.PublishedContentRequest = new PublishedContentRequest(
                umbracoContext.CleanedUmbracoUrl, umbracoContext.RoutingContext,
                UmbracoConfig.For.UmbracoSettings().WebRouting, s => Roles.Provider.GetRolesForUser(s))
            {
                PublishedContent = found
            };

            //allows inheritors to change the pcr
            PreparePublishedContentRequest(umbracoContext.PublishedContentRequest);

            //create the render model
            var renderModel = new RenderModel(umbracoContext.PublishedContentRequest.PublishedContent, umbracoContext.PublishedContentRequest.Culture);

            //assigns the required tokens to the request
            requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, renderModel);
            requestContext.RouteData.DataTokens.Add(Core.Constants.Web.PublishedDocumentRequestDataToken, umbracoContext.PublishedContentRequest);
            requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbracoContext);
            //this is used just for a flag that this is an umbraco custom route
            requestContext.RouteData.DataTokens.Add(Core.Constants.Web.CustomRouteDataToken, true);

            //Here we need to detect if a SurfaceController has posted
            var formInfo = RenderRouteHandler.GetFormInfo(requestContext);

            if (formInfo != null)
            {
                var def = new RouteDefinition
                {
                    ActionName              = requestContext.RouteData.GetRequiredString("action"),
                    ControllerName          = requestContext.RouteData.GetRequiredString("controller"),
                    PublishedContentRequest = umbracoContext.PublishedContentRequest
                };

                //set the special data token to the current route definition
                requestContext.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken] = def;

                return(RenderRouteHandler.HandlePostedValues(requestContext, formInfo));
            }

            return(new MvcHandler(requestContext));
        }
Exemple #3
0
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            var umbracoContext = UmbracoContext.Current;

            var found = FindContent(requestContext, umbracoContext);

            if (found == null)
            {
                return(new NotFoundHandler());
            }

            umbracoContext.PublishedContentRequest = new PublishedContentRequest(
                umbracoContext.CleanedUmbracoUrl, umbracoContext.RoutingContext)
            {
                PublishedContent = found
            };

            //allows inheritors to change the pcr
            PreparePublishedContentRequest(umbracoContext.PublishedContentRequest);

            //create the render model
            var renderModel = new RenderModel(umbracoContext.PublishedContentRequest.PublishedContent, umbracoContext.PublishedContentRequest.Culture);

            //assigns the required tokens to the request
            requestContext.RouteData.DataTokens.Add("umbraco", renderModel);
            requestContext.RouteData.DataTokens.Add("umbraco-doc-request", umbracoContext.PublishedContentRequest);
            requestContext.RouteData.DataTokens.Add("umbraco-context", umbracoContext);
            //this is used just for a flag that this is an umbraco custom route
            requestContext.RouteData.DataTokens.Add("umbraco-custom-route", true);

            //Here we need to detect if a SurfaceController has posted
            var formInfo = RenderRouteHandler.GetFormInfo(requestContext);

            if (formInfo != null)
            {
                var def = new RouteDefinition
                {
                    ActionName              = requestContext.RouteData.GetRequiredString("action"),
                    ControllerName          = requestContext.RouteData.GetRequiredString("controller"),
                    PublishedContentRequest = umbracoContext.PublishedContentRequest
                };

                //set the special data token to the current route definition
                requestContext.RouteData.DataTokens["umbraco-route-def"] = def;

                return(RenderRouteHandler.HandlePostedValues(requestContext, formInfo));
            }

            return(new MvcHandler(requestContext));
        }
Exemple #4
0
        /// <summary>
        /// Returns a RouteDefinition object based on the current content request
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        internal virtual RouteDefinition GetUmbracoRouteDefinition(RequestContext requestContext, PublishedRequest request)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException(nameof(requestContext));
            }
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var defaultControllerType = Current.DefaultRenderMvcControllerType;
            var defaultControllerName = ControllerExtensions.GetControllerName(defaultControllerType);
            //creates the default route definition which maps to the 'UmbracoController' controller
            var def = new RouteDefinition
            {
                ControllerName   = defaultControllerName,
                ControllerType   = defaultControllerType,
                PublishedRequest = request,
                ActionName       = ((Route)requestContext.RouteData.Route).Defaults["action"].ToString(),
                HasHijackedRoute = false
            };

            //check that a template is defined), if it doesn't and there is a hijacked route it will just route
            // to the index Action
            if (request.HasTemplate)
            {
                //the template Alias should always be already saved with a safe name.
                //if there are hyphens in the name and there is a hijacked route, then the Action will need to be attributed
                // with the action name attribute.
                var templateName = request.TemplateAlias.Split('.')[0].ToSafeAlias();
                def.ActionName = templateName;
            }

            //check if there's a custom controller assigned, base on the document type alias.
            var controllerType = _controllerFactory.GetControllerTypeInternal(requestContext, request.PublishedContent.ContentType.Alias);

            //check if that controller exists
            if (controllerType != null)
            {
                //ensure the controller is of type IRenderMvcController and ControllerBase
                if (TypeHelper.IsTypeAssignableFrom <IRenderController>(controllerType) &&
                    TypeHelper.IsTypeAssignableFrom <ControllerBase>(controllerType))
                {
                    //set the controller and name to the custom one
                    def.ControllerType = controllerType;
                    def.ControllerName = ControllerExtensions.GetControllerName(controllerType);
                    if (def.ControllerName != defaultControllerName)
                    {
                        def.HasHijackedRoute = true;
                    }
                }
                else
                {
                    Current.Logger.Warn <RenderRouteHandler>("The current Document Type {ContentTypeAlias} matches a locally declared controller of type {ControllerName}. Custom Controllers for Umbraco routing must implement '{UmbracoRenderController}' and inherit from '{UmbracoControllerBase}'.",
                                                             request.PublishedContent.ContentType.Alias,
                                                             controllerType.FullName,
                                                             typeof(IRenderController).FullName,
                                                             typeof(ControllerBase).FullName);

                    //we cannot route to this custom controller since it is not of the correct type so we'll continue with the defaults
                    // that have already been set above.
                }
            }

            //store the route definition
            requestContext.RouteData.DataTokens[Core.Constants.Web.UmbracoRouteDefinitionDataToken] = def;

            return(def);
        }
        /// <summary>
        /// Handles a posted form to an Umbraco Url and ensures the correct controller is routed to and that
        /// the right DataTokens are set.
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="postedInfo"></param>
        /// <param name="routeDefinition">The original route definition that would normally be used to route if it were not a POST</param>
        private IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo, RouteDefinition routeDefinition)
        {
            var standardArea = Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea;

            //set the standard route values/tokens
            requestContext.RouteData.Values["controller"] = postedInfo.ControllerName;
            requestContext.RouteData.Values["action"]     = postedInfo.ActionName;
            requestContext.RouteData.DataTokens["area"]   = postedInfo.Area;

            IHttpHandler handler = new MvcHandler(requestContext);

            //ensure the controllerType is set if found, meaning it is a plugin, not locally declared
            if (postedInfo.Area != standardArea)
            {
                //requestContext.RouteData.Values["controllerType"] = postedInfo.ControllerType;
                //find the other data tokens for this route and merge... things like Namespace will be included here
                using (RouteTable.Routes.GetReadLock())
                {
                    var surfaceRoute = RouteTable.Routes.OfType <Route>()
                                       .SingleOrDefault(x => x.Defaults != null &&
                                                        x.Defaults.ContainsKey("controller") &&
                                                        x.Defaults["controller"].ToString() == postedInfo.ControllerName &&
                                                        x.DataTokens.ContainsKey("area") &&
                                                        x.DataTokens["area"].ToString() == postedInfo.Area);
                    if (surfaceRoute == null)
                    {
                        throw new InvalidOperationException("Could not find a Surface controller route in the RouteTable for controller name " + postedInfo.ControllerName + " and within the area of " + postedInfo.Area);
                    }
                    //set the 'Namespaces' token so the controller factory knows where to look to construct it
                    if (surfaceRoute.DataTokens.ContainsKey("Namespaces"))
                    {
                        requestContext.RouteData.DataTokens["Namespaces"] = surfaceRoute.DataTokens["Namespaces"];
                    }
                    handler = surfaceRoute.RouteHandler.GetHttpHandler(requestContext);
                }
            }

            //store the original URL this came in on
            requestContext.RouteData.DataTokens["umbraco-item-url"] = requestContext.HttpContext.Request.Url.AbsolutePath;
            //store the original route definition
            requestContext.RouteData.DataTokens["umbraco-route-def"] = routeDefinition;

            return(handler);
        }
        /// <summary>
        /// Creates a controller using the controller factory
        /// </summary>
        private static ControllerBase CreateController(ControllerContext context, IControllerFactory factory, RouteDefinition routeDef)
        {
            var controller = factory.CreateController(context.RequestContext, routeDef.ControllerName) as ControllerBase;

            if (controller == null)
            {
                throw new InvalidOperationException("Could not create controller with name " + routeDef.ControllerName + ".");
            }

            return(controller);
        }
        /// <summary>
        /// Creates a controller using the controller factory
        /// </summary>
        private static ControllerBase CreateController(ControllerContext context, IControllerFactory factory, RouteDefinition routeDef)
        {
            var controller = factory.CreateController(context.RequestContext, routeDef.ControllerName) as ControllerBase;

            if (controller == null)
                throw new InvalidOperationException("Could not create controller with name " + routeDef.ControllerName + ".");

            return controller;
        }
        /// <summary>
        /// Returns a RouteDefinition object based on the current renderModel
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="publishedContentRequest"></param>
        /// <returns></returns>
        internal virtual RouteDefinition GetUmbracoRouteDefinition(RequestContext requestContext, PublishedContentRequest publishedContentRequest)
        {
            var defaultControllerType = DefaultRenderMvcControllerResolver.Current.GetDefaultControllerType();
            var defaultControllerName = ControllerExtensions.GetControllerName(defaultControllerType);
            //creates the default route definition which maps to the 'UmbracoController' controller
            var def = new RouteDefinition
            {
                ControllerName          = defaultControllerName,
                ControllerType          = defaultControllerType,
                PublishedContentRequest = publishedContentRequest,
                ActionName       = ((Route)requestContext.RouteData.Route).Defaults["action"].ToString(),
                HasHijackedRoute = false
            };

            //check that a template is defined), if it doesn't and there is a hijacked route it will just route
            // to the index Action
            if (publishedContentRequest.HasTemplate)
            {
                //the template Alias should always be already saved with a safe name.
                //if there are hyphens in the name and there is a hijacked route, then the Action will need to be attributed
                // with the action name attribute.
                var templateName = publishedContentRequest.TemplateAlias.Split('.')[0].ToSafeAlias();
                def.ActionName = templateName;
            }

            //check if there's a custom controller assigned, base on the document type alias.
            var controllerType = _controllerFactory.GetControllerTypeInternal(requestContext, publishedContentRequest.PublishedContent.DocumentTypeAlias);

            //check if that controller exists
            if (controllerType != null)
            {
                //ensure the controller is of type 'IRenderMvcController' and ControllerBase
                if (TypeHelper.IsTypeAssignableFrom <IRenderMvcController>(controllerType) &&
                    TypeHelper.IsTypeAssignableFrom <ControllerBase>(controllerType))
                {
                    //set the controller and name to the custom one
                    def.ControllerType = controllerType;
                    def.ControllerName = ControllerExtensions.GetControllerName(controllerType);
                    if (def.ControllerName != defaultControllerName)
                    {
                        def.HasHijackedRoute = true;
                    }
                }
                else
                {
                    LogHelper.Warn <RenderRouteHandler>(
                        "The current Document Type {0} matches a locally declared controller of type {1}. Custom Controllers for Umbraco routing must implement '{2}' and inherit from '{3}'.",
                        () => publishedContentRequest.PublishedContent.DocumentTypeAlias,
                        () => controllerType.FullName,
                        () => typeof(IRenderMvcController).FullName,
                        () => typeof(ControllerBase).FullName);
                    //exit as we cannnot route to the custom controller, just route to the standard one.
                    return(def);
                }
            }

            //store the route definition
            requestContext.RouteData.DataTokens["umbraco-route-def"] = def;

            return(def);
        }