private static async Task ServePrerenderResult(HttpContext context, RenderToStringResult renderResult)
        {
            context.Response.Clear();

            if (!string.IsNullOrEmpty(renderResult.RedirectUrl))
            {
                var permanentRedirect = renderResult.StatusCode.GetValueOrDefault() == 301;
                context.Response.Redirect(renderResult.RedirectUrl, permanentRedirect);
            }
            else
            {
                // The Globals property exists for back-compatibility but is meaningless
                // for prerendering that returns complete HTML pages
                if (renderResult.Globals != null)
                {
                    throw new InvalidOperationException($"{nameof(renderResult.Globals)} is not " +
                                                        $"supported when prerendering via {nameof(UseSpaPrerendering)}(). Instead, " +
                                                        $"your prerendering logic should return a complete HTML page, in which you " +
                                                        $"embed any information you wish to return to the client.");
                }

                if (renderResult.StatusCode.HasValue)
                {
                    context.Response.StatusCode = renderResult.StatusCode.Value;
                }

                context.Response.ContentType = "text/html";
                await context.Response.WriteAsync(renderResult.Html);
            }
        }
        public void HandlesNullGlobals()
        {
            // Arrange
#pragma warning disable CS0618 // Type or member is obsolete
            var renderToStringResult = new RenderToStringResult();
#pragma warning restore CS0618 // Type or member is obsolete
            renderToStringResult.Globals = null;

            // Act
            var actualScript = renderToStringResult.CreateGlobalsAssignmentScript();

            // Assert
            Assert.Equal(string.Empty, actualScript);
        }
Exemple #3
0
        public static int?GetStatusCodeFromMeta(this RenderToStringResult renderToStringResult)
        {
            // --- Parse the meta description
            var meta            = renderToStringResult.Globals.Descendants().FirstOrDefault(o => o.Path == "meta").First.ToString();
            var statusCodeMatch = Regex.Match(meta, "property=\"statusCode\" content\\s*=\\s*(?:\"(?<1>[^\"]*)\"|(?<1>\\S+))");
            var statusCode      = statusCodeMatch.Groups[1].Value;

            if (string.IsNullOrEmpty(statusCode))
            {
                return(null);
            }

            return(Convert.ToInt32(statusCodeMatch.Groups[1].Value));
        }
        public void HandlesGlobalsWithCorrectStringEncoding()
        {
            // Arrange
#pragma warning disable CS0618 // Type or member is obsolete
            var renderToStringResult = new RenderToStringResult();
#pragma warning restore CS0618 // Type or member is obsolete
            renderToStringResult.Globals = ToJObject(new Dictionary <string, object>
            {
                { "Va<l'u\"e", "</tag>\"'}\u260E" }
            });

            // Act
            var actualScript = renderToStringResult.CreateGlobalsAssignmentScript();

            // Assert
            var expectedScript = @"window[""Va\u003Cl\u0027u\u0022e""] = JSON.parse(""\u0022\u003C/tag\u003E\\\u0022\u0027}\u260E\u0022"");";
            Assert.Equal(expectedScript, actualScript);
        }
        private static async Task ApplyRenderResult(HttpContext context, RenderToStringResult renderResult)
        {
            if (!string.IsNullOrEmpty(renderResult.RedirectUrl))
            {
                context.Response.Redirect(renderResult.RedirectUrl);
            }
            else
            {
                // The Globals property exists for back-compatibility but is meaningless
                // for prerendering that returns complete HTML pages
                if (renderResult.Globals != null)
                {
                    throw new Exception($"{nameof(renderResult.Globals)} is not supported when prerendering via {nameof(UseSpaPrerendering)}(). Instead, your prerendering logic should return a complete HTML page, in which you embed any information you wish to return to the client.");
                }

                context.Response.ContentType = "text/html";
                await context.Response.WriteAsync(renderResult.Html);
            }
        }
        public void HandlesGlobalsWithMultipleProperties()
        {
            // Arrange
#pragma warning disable CS0618 // Type or member is obsolete
            var renderToStringResult = new RenderToStringResult();
#pragma warning restore CS0618 // Type or member is obsolete
            renderToStringResult.Globals = ToJObject(new
            {
                FirstProperty  = "first value",
                SecondProperty = new[] { "Array entry 0", "Array entry 1" }
            });

            // Act
            var actualScript = renderToStringResult.CreateGlobalsAssignmentScript();

            // Assert
            var expectedScript = @"window[""FirstProperty""] = JSON.parse(""\u0022first value\u0022"");" +
                                 @"window[""SecondProperty""] = JSON.parse(""[\u0022Array entry 0\u0022,\u0022Array entry 1\u0022]"");";
            Assert.Equal(expectedScript, actualScript);
        }
Exemple #7
0
        public async Task <IActionResult> Index([FromServices] ISpaPrerenderer prerenderer, [FromServices] IMemoryCache cache)
        {
            IHttpRequestFeature requestFeature = this.Request.HttpContext.Features.Get <IHttpRequestFeature>();
            string unencodedPathAndQuery       = requestFeature.RawTarget;

            RenderToStringResult prerenderResult = await cache.GetOrCreateAsync(unencodedPathAndQuery, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(10);
                entry.SlidingExpiration = TimeSpan.FromDays(3);
                return(prerenderer.RenderToString("angular/dist-server/server", customDataParameter: new { request = this.Request.AbstractHttpContextRequestInfo() }));
            });

            this.ViewData["SpaHtml"]      = prerenderResult.Html;
            this.ViewData["Title"]        = prerenderResult.Globals["title"];
            this.ViewData["Scripts"]      = prerenderResult.Globals["scripts"];
            this.ViewData["Styles"]       = prerenderResult.Globals["styles"];
            this.ViewData["Meta"]         = prerenderResult.Globals["meta"];
            this.ViewData["Links"]        = prerenderResult.Globals["links"];
            this.ViewData["TransferData"] = prerenderResult.Globals["transferData"];

            return(View());
        }