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