无需为Angular应用程序进行服务器端渲染即可即时更改Index.html文件中的值

问题描述

我有一个使用Angular(10)作为前端的网站。在有角度的应用程序背后,ASP.Net Core 3.1提供了所有文件和api查询。

我想让open graph与该网站合作,以使社交媒体中的引荐链接更好。在google上进行的任何搜索都会导致您发现需要启用服务器端渲染。这样的页面:Server-side rendering in ASP.NET Core Angular

我真的不想实现SSR,因为它有很多要求,这似乎有些过头了。因此,我着手用Asp net core中的中间件解决此问题。

现在我有一个可行的解决方案。

下面的代码可以工作,并根据请求更改我的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))" /> 

我想知道这是否可以改进,或者这是一个可怕的主意,如果可以,为什么。

通过在app.UseMiddleware(typeof(OpenGraphsMiddleWare));的Configure方法中放置Startup.cs来运行代码。

代码:

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,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;
        }
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...