예제 #1
0
        // returns a value indicating whether redirection took place and the request has
        // been completed - because we don't want to Response.End() here to terminate
        // everything properly.
        internal static bool HandleHttpResponseStatus(HttpContextBase context, PublishedContentRequest pcr)
        {
            var end      = false;
            var response = context.Response;

            LogHelper.Debug <UmbracoModule>("Response status: Redirect={0}, Is404={1}, StatusCode={2}",
                                            () => pcr.IsRedirect ? (pcr.IsRedirectPermanent ? "permanent" : "redirect") : "none",
                                            () => pcr.Is404 ? "true" : "false", () => pcr.ResponseStatusCode);

            if (pcr.IsRedirect)
            {
                if (pcr.IsRedirectPermanent)
                {
                    response.RedirectPermanent(pcr.RedirectUrl, false); // do not end response
                }
                else
                {
                    response.Redirect(pcr.RedirectUrl, false); // do not end response
                }
                end = true;
            }
            else if (pcr.Is404)
            {
                response.StatusCode             = 404;
                response.TrySkipIisCustomErrors = UmbracoSettings.For <WebRouting>().TrySkipIisCustomErrors;
            }

            if (pcr.ResponseStatusCode > 0)
            {
                // set status code -- even for redirects
                response.StatusCode        = pcr.ResponseStatusCode;
                response.StatusDescription = pcr.ResponseStatusDescription;
            }
            //if (pcr.IsRedirect)
            //    response.End(); // end response -- kills the thread and does not return!

            if (pcr.IsRedirect)
            {
                response.Flush();
                // bypass everything and directly execute EndRequest event -- but returns
                context.ApplicationInstance.CompleteRequest();
                // though some say that .CompleteRequest() does not properly shutdown the response
                // and the request will hang until the whole code has run... would need to test?
                LogHelper.Debug <UmbracoModule>("Response status: redirecting, complete request now.");
            }

            return(end);
        }
        /// <summary>
        /// Sets the requested content, following an internal redirect.
        /// </summary>
        /// <param name="content">The requested content.</param>
        /// <remarks>Depending on <c>UmbracoSettings.InternalRedirectPreservesTemplate</c>, will
        /// preserve or reset the template, if any.</remarks>
        public void SetInternalRedirectPublishedContent(IPublishedContent content)
        {
            EnsureWriteable();

            // unless a template has been set already by the finder,
            // template should be null at that point.
            var initial  = IsInitialPublishedContent;
            var template = _template;

            PublishedContent = content;
            IsInternalRedirectPublishedContent = (initial && !IsInitialPublishedContent);
            if (IsInternalRedirectPublishedContent && UmbracoSettings.For <WebRouting>().InternalRedirectPreservesTemplate)
            {
                _template = template;
            }
        }
예제 #3
0
        /// <summary>
        /// Sets the requested content, following an internal redirect.
        /// </summary>
        /// <param name="content">The requested content.</param>
        /// <remarks>Depending on <c>UmbracoSettings.InternalRedirectPreservesTemplate</c>, will
        /// preserve or reset the template, if any.</remarks>
        public void SetInternalRedirectPublishedContent(IPublishedContent content)
        {
            EnsureWriteable();

            // unless a template has been set already by the finder,
            // template should be null at that point.

            // IsInternalRedirect if IsInitial, or already IsInternalRedirect
            var isInternalRedirect = IsInitialPublishedContent || IsInternalRedirectPublishedContent;

            // redirecting to self
            if (content.Id == PublishedContent.Id) // neither can be null
            {
                // no need to set PublishedContent, we're done
                IsInternalRedirectPublishedContent = isInternalRedirect;
                return;
            }

            // else

            // save
            var template        = _template;
            var renderingEngine = RenderingEngine;

            // set published content - this resets the template, and sets IsInternalRedirect to false
            PublishedContent = content;
            IsInternalRedirectPublishedContent = isInternalRedirect;

            // must restore the template if it's an internal redirect & the config option is set
            if (isInternalRedirect && UmbracoSettings.For <WebRouting>().InternalRedirectPreservesTemplate)
            {
                // restore
                _template       = template;
                RenderingEngine = renderingEngine;
            }
        }
예제 #4
0
        /// <summary>
        /// Finds a template for the current node, if any.
        /// </summary>
        private void FindTemplate()
        {
            // NOTE: at the moment there is only 1 way to find a template, and then ppl must
            // use the Prepared event to change the template if they wish. Should we also
            // implement an ITemplateFinder logic?

            const string tracePrefix = "FindTemplate: ";

            if (_pcr.PublishedContent == null)
            {
                _pcr.TemplateModel = null;
                return;
            }

            // read the alternate template alias, from querystring, form, cookie or server vars,
            // only if the published content is the initial once, else the alternate template
            // does not apply
            // + optionnally, apply the alternate template on internal redirects
            var useAltTemplate = _pcr.IsInitialPublishedContent ||
                                 (UmbracoSettings.For <WebRouting>().InternalRedirectPreservesTemplate&& _pcr.IsInternalRedirectPublishedContent);
            string altTemplate = useAltTemplate
                ? _routingContext.UmbracoContext.HttpContext.Request[Constants.Conventions.Url.AltTemplate]
                                : null;

            if (string.IsNullOrWhiteSpace(altTemplate))
            {
                // we don't have an alternate template specified. use the current one if there's one already,
                // which can happen if a content lookup also set the template (LookupByNiceUrlAndTemplate...),
                // else lookup the template id on the document then lookup the template with that id.

                if (_pcr.HasTemplate)
                {
                    LogHelper.Debug <PublishedContentRequest>("{0}Has a template already, and no alternate template.", () => tracePrefix);
                    return;
                }

                // TODO: When we remove the need for a database for templates, then this id should be irrelavent,
                // not sure how were going to do this nicely.

                var templateId = _pcr.PublishedContent.TemplateId;

                if (templateId > 0)
                {
                    LogHelper.Debug <PublishedContentRequestEngine>("{0}Look for template id={1}", () => tracePrefix, () => templateId);
                    var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateId);
                    if (template == null)
                    {
                        throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render");
                    }
                    _pcr.TemplateModel = template;
                    LogHelper.Debug <PublishedContentRequestEngine>("{0}Got template id={1} alias=\"{2}\"", () => tracePrefix, () => template.Id, () => template.Alias);
                }
                else
                {
                    LogHelper.Debug <PublishedContentRequestEngine>("{0}No specified template.", () => tracePrefix);
                }
            }
            else
            {
                // we have an alternate template specified. lookup the template with that alias
                // this means the we override any template that a content lookup might have set
                // so /path/to/page/template1?altTemplate=template2 will use template2

                // ignore if the alias does not match - just trace

                if (_pcr.HasTemplate)
                {
                    LogHelper.Debug <PublishedContentRequestEngine>("{0}Has a template already, but also an alternate template.", () => tracePrefix);
                }
                LogHelper.Debug <PublishedContentRequestEngine>("{0}Look for alternate template alias=\"{1}\"", () => tracePrefix, () => altTemplate);

                var template = ApplicationContext.Current.Services.FileService.GetTemplate(altTemplate);
                if (template != null)
                {
                    _pcr.TemplateModel = template;
                    LogHelper.Debug <PublishedContentRequestEngine>("{0}Got template id={1} alias=\"{2}\"", () => tracePrefix, () => template.Id, () => template.Alias);
                }
                else
                {
                    LogHelper.Debug <PublishedContentRequestEngine>("{0}The template with alias=\"{1}\" does not exist, ignoring.", () => tracePrefix, () => altTemplate);
                }
            }

            if (!_pcr.HasTemplate)
            {
                LogHelper.Debug <PublishedContentRequestEngine>("{0}No template was found.", () => tracePrefix);

                // initial idea was: if we're not already 404 and UmbracoSettings.HandleMissingTemplateAs404 is true
                // then reset _pcr.Document to null to force a 404.
                //
                // but: because we want to let MVC hijack routes even though no template is defined, we decide that
                // a missing template is OK but the request will then be forwarded to MVC, which will need to take
                // care of everything.
                //
                // so, don't set _pcr.Document to null here
            }
            else
            {
                LogHelper.Debug <PublishedContentRequestEngine>("{0}Running with template id={1} alias=\"{2}\"", () => tracePrefix, () => _pcr.TemplateModel.Id, () => _pcr.TemplateModel.Alias);
            }
        }