动态更改Index.html文件中的值,而无需为Angular应用程序进行服务器端渲染

动态更改Index.html文件中的值,而无需为Angular应用程序进行服务器端渲染,angular,asp.net-core,asp.net-core-3.1,angular10,Angular,Asp.net Core,Asp.net Core 3.1,Angular10,我有一个网站,使用角(10)作为前端。在angular应用程序ASP.NETCore3.1背后,提供所有文件和api查询 我想开始与这个网站的工作,使社会媒体的推荐链接更好。谷歌上的任何搜索都会导致您发现需要启用服务器端渲染。像这样的页面: 我真的不想实现SSR,因为它有相当多的需求,而且在这方面似乎有些过分。所以我开始用Asp net内核中的中间件来解决这个问题 现在我有了一个有效的解决方案 下面的代码根据请求工作并更改my index.html文件中的以下值。它拦截对/(索引)的请求,或对/

我有一个网站,使用角(10)作为前端。在angular应用程序ASP.NETCore3.1背后,提供所有文件和api查询

我想开始与这个网站的工作,使社会媒体的推荐链接更好。谷歌上的任何搜索都会导致您发现需要启用服务器端渲染。像这样的页面:

我真的不想实现SSR,因为它有相当多的需求,而且在这方面似乎有些过分。所以我开始用Asp net内核中的中间件来解决这个问题

现在我有了一个有效的解决方案

下面的代码根据请求工作并更改my index.html文件中的以下值。它拦截对
/
(索引)的请求,或对
/details/
页面的任何请求

<meta name="description" content="((og:description))">
<meta property="og:title" content="((og:title))" />
<meta property="og:description" content="((og:description))" />
<meta property="og:image" content="((og:previewImage))" /> 

这段代码也相当快。基线静态页面请求需要我的开发人员机器6毫秒才能处理。这段代码在第一次运行时需要40毫秒,然后在任何重复查询时需要6毫秒。
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;

namespace NiftySite.Web.Middleware
{
    public class OpenGraphMiddleWare
    {
        private readonly RequestDelegate _next;

        private readonly static OpenGraphsData _defaultOpenGraph = new OpenGraphsData(
            "mysite.com",
            "Really nifty description.",
            "https://myurl.com/favicon.ico"
        );

        private static Dictionary<string, string> _cache = new Dictionary<string, string>();

        public OpenGraphMiddleWare(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context, IDetailsProcess listItemProcess, ILogger<OpenGraphMiddleWare> logger)
        {
            try
            {
                await HandleOGRequest(context, listItemProcess, logger);
            }
            catch (Exception e)
            {
                logger.LogError(e, $"OpenGraphMiddleWare failed: {e.Message}");
            }
        }

        private async Task HandleOGRequest(HttpContext context, IDetailsProcess listItemProcess, ILogger<OpenGraphMiddleWare> logger)
        {
            var path = context?.Request?.Path.ToString() ?? string.Empty;
            if (path != "/" && path.StartsWith("/details/") == false)
            {
                await _next(context);
            }
            else
            {
                context.Response.ContentType = "text/html";
                using (var originalIndexStream = new FileStream("wwwroot/index.html", FileMode.Open))
                {
                    using (var streamReader = new StreamReader(originalIndexStream))
                    {
                        var pageString = string.Empty;
                        if (_cache.ContainsKey(path))
                        {
                            pageString = _cache[path];
                        }
                        else
                        {
                            var indexString = await streamReader.ReadToEndAsync();
                            pageString = await InjectOpenGraphData(indexString, path, listItemProcess);
                        }

                        byte[] byteArray = Encoding.UTF8.GetBytes(pageString);
                        using (MemoryStream resulStream = new MemoryStream(byteArray))
                        {
                            await resulStream.CopyToAsync(context.Response.Body);
                        }
                    }
                }
            }
        }

        private async Task<string> InjectOpenGraphData(string pageString, string path, IDetailsProcess listItemProcess)
        {
            var details = await GetOpenGraphValues(path, listItemProcess);

            pageString = pageString
                .Replace("((og:title))", details.Title)
                .Replace("((og:description))", details.Description)
                .Replace("((og:previewImage))", details.ImagePath);

            _cache[path] = pageString;

            return pageString;
        }

        private async Task<OpenGraphsData> GetOpenGraphValues(string path, IDetailsProcess listItemProcess)
        {
            var auctionId = GetAuctionId(path);
            if (auctionId != null)
            {
                var details = await listItemProcess.GetSingleAuctionListItem(auctionId.Value);
                return new OpenGraphsData("Details: " + details.Title, details.Advert, details.Thumbnail);
            }
            return _defaultOpenGraph;
        }

        private int? GetAuctionId(string path)
        {
            var auctionIdString = Regex.Match(path, @"\d+").Value;
            if (int.TryParse(auctionIdString, out int auctionId))
                return auctionId;

            return null;
        }
    }

    class OpenGraphsData
    {
        public string Title { get; }
        public string Description { get; }
        public string ImagePath { get; }

        public OpenGraphsData(string title, string description, string imagePath)
        {
            Title = title;
            Description = description;
            ImagePath = imagePath;
        }
    }
}