C# 是否可以在控制器内执行ViewComponent并将HTML存储为字符串
我目前有几个视图组件,在许多不同的地方使用。我希望能够将调用视图组件时生成的HTML存储到字符串变量中,以便将HTML用于其他用途(如电子邮件) 我看了一些问题和帖子,但没有找到一个符合我要求的。我当前存储了ViewComponentResult以供使用,但ExecuterResult()返回void,因此无法使用它 我希望能够操作视图组件结果以执行,然后返回将发送到浏览器以显示的HTML。然后我可以用它作为电子邮件正文。但是,在不知道结果视图的完整路径的情况下,我目前还无法获得HTML 一种方法是制作“您自己的”html标记(更像是现有html上的扩展方法)并实现 您可以在重写时访问或更改内容,我有一个类,它扩展了几个html标记来管理custome全球化,请查看代码,看看这是否对您有所帮助 在您的页面中,您可以通过添加属性“拥有”html,就像我在这里用我的属性cats语言键演示的那样:C# 是否可以在控制器内执行ViewComponent并将HTML存储为字符串,c#,asp.net-core-mvc,asp.net-core-viewcomponent,C#,Asp.net Core Mvc,Asp.net Core Viewcomponent,我目前有几个视图组件,在许多不同的地方使用。我希望能够将调用视图组件时生成的HTML存储到字符串变量中,以便将HTML用于其他用途(如电子邮件) 我看了一些问题和帖子,但没有找到一个符合我要求的。我当前存储了ViewComponentResult以供使用,但ExecuterResult()返回void,因此无法使用它 我希望能够操作视图组件结果以执行,然后返回将发送到浏览器以显示的HTML。然后我可以用它作为电子邮件正文。但是,在不知道结果视图的完整路径的情况下,我目前还无法获得HTML 一种方
<div cats-language-key="Home-S2-h1-p1">
</p>
[HtmlTargetElement("p",Attributes = CatsLanguageKey)]
[HtmlTargetElement("span", Attributes = CatsLanguageKey)]
[HtmlTargetElement("a", Attributes = CatsLanguageKey)]
[HtmlTargetElement("li", Attributes = CatsLanguageKey)]
[HtmlTargetElement("h1", Attributes = CatsLanguageKey)]
[HtmlTargetElement("h2", Attributes = CatsLanguageKey)]
[HtmlTargetElement("h3", Attributes = CatsLanguageKey)]
[HtmlTargetElement("h4", Attributes = CatsLanguageKey)]
[HtmlTargetElement("div", Attributes = CatsLanguageKey)]
public class LanguageTagHelper: TagHelper
{
private const string CatsLanguageKey= "cats-language-key";
private readonly ILanguageRepository _repository;
private readonly ClaimsPrincipal _user;
private readonly IMemoryCache _memoryCache;
public LanguageTagHelper(ILanguageRepository repository, IHttpContextAccessor context, IMemoryCache memoryCache)
{
_repository = repository;
_user = context.HttpContext.User;
_memoryCache = memoryCache;
}
[HtmlAttributeName(CatsLanguageKey)]
public string Key { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
if (!childContent.IsEmptyOrWhiteSpace)
{
var textItem = _repository.GetHtml(Key, childContent.GetContent().Trim());
if (_user.Identity.IsAuthenticated && _user.IsInRole(MagicStrings.ROLE_TEXTER))
{
output.Attributes.Add("data-language-target", textItem.Language);
output.Attributes.Add("data-language-key", textItem.Key);
var html = new HtmlString(textItem.Text);
output.Content.SetHtmlContent(html);
_memoryCache.Remove(Key);
}
else
{
string text = string.Empty;
if (!_memoryCache.TryGetValue(Key, out text))
{
text = Regex.Replace(textItem.Text, @">\s+<", "><", RegexOptions.Compiled | RegexOptions.Multiline);
text = Regex.Replace(text, @"<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->)(.|\n))*-->", "", RegexOptions.Compiled | RegexOptions.Multiline);
text = Regex.Replace(text, @"^\s+", "", RegexOptions.Compiled | RegexOptions.Multiline);
text = Regex.Replace(text, @"\r\n?|\n", "", RegexOptions.Compiled | RegexOptions.Multiline);
text = Regex.Replace(text, @"\s+", " ", RegexOptions.Compiled | RegexOptions.Multiline);
_memoryCache.Set(Key, text, new MemoryCacheEntryOptions() { Priority= CacheItemPriority.Low, SlidingExpiration= new TimeSpan(hours:1,minutes:0,seconds:0) });
}
var html = new HtmlString(text);
output.Content.SetHtmlContent(html);
}
}
}
}
因此,我给了您两个选项,一个是标记级别的选项,比如div,另一个基本上是您喜欢的大小。我能够找到一个方法,它完全满足我的需要(将返回的HTML作为字符串),如中的一个答案所述 我使用的代码块是
public async Task<string> RenderViewComponent(string viewComponent, object args) {
var sp = HttpContext.RequestServices;
var helper = new DefaultViewComponentHelper(
sp.GetRequiredService<IViewComponentDescriptorCollectionProvider>(),
HtmlEncoder.Default,
sp.GetRequiredService<IViewComponentSelector>(),
sp.GetRequiredService<IViewComponentInvokerFactory>(),
sp.GetRequiredService<IViewBufferScope>());
using (var writer = new StringWriter()) {
var context = new ViewContext(ControllerContext, NullView.Instance, ViewData, TempData, writer, new HtmlHelperOptions());
helper.Contextualize(context);
var result = await helper.InvokeAsync(viewComponent, args);
result.WriteTo(writer, HtmlEncoder.Default);
await writer.FlushAsync();
return writer.
}
}
公共异步任务RenderViewComponent(字符串viewComponent,对象参数){
var sp=HttpContext.RequestServices;
var helper=新的DefaultViewComponentHelper(
sp.GetRequiredService(),
HtmlEncoder.Default,
sp.GetRequiredService(),
sp.GetRequiredService(),
sp.GetRequiredService());
使用(var writer=new StringWriter()){
var context=newviewcontext(ControllerContext,NullView.Instance,ViewData,TempData,writer,newhtmlhelpropoptions());
语境化(context);
var result=await helper.InvokeAsync(viewComponent,args);
WriteTo(writer,HtmlEncoder.Default);
等待writer.FlushAsync();
回归作家。
}
}
谢谢你的来信。我不确定它是否完全回答了我的问题,但我已经设法找到了另一个我以前忽略的堆栈溢出帖子。再次感谢。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.IO;
using System.Threading.Tasks;
using System.Text;
using System.Text.RegularExpressions;
namespace CATS.Web.Shared.Infrastructure.Middleware
{
using CATS.Web.Shared.Repositories;
public class HtmlMinificationMiddleware
{
private RequestDelegate _next;
StatsRepository _stats;
private HtmlMinificationOptions _minificationOptions;
public HtmlMinificationMiddleware(RequestDelegate next, StatsRepository stats)
: this(next, null, stats)
{
}
public HtmlMinificationMiddleware(RequestDelegate next, HtmlMinificationOptions minificationOptions, StatsRepository stats)
{
_next = next;
_minificationOptions = minificationOptions;
_stats = stats;
}
public async Task Invoke(HttpContext context)
{
var stream = context.Response.Body;
if (_minificationOptions != null)
{
var filter = _minificationOptions.ExcludeFilter;
if (Regex.IsMatch(context.Request.Path, filter))
{
await _next(context);
return;
}
}
long size = 0;
try
{
using (var buffer = new MemoryStream())
{
context.Response.Body = buffer;
await _next(context);
var isHtml = context.Response.ContentType?.ToLower().Contains("text/html");
buffer.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(buffer))
{
string responseBody = await reader.ReadToEndAsync();
var backup = string.Copy(responseBody);
if (context.Response.StatusCode == 200 && isHtml.GetValueOrDefault())
{
try
{
responseBody = Regex.Replace(responseBody, @">\s+<", "><", RegexOptions.Compiled | RegexOptions.Multiline);
responseBody = Regex.Replace(responseBody, @"<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->)(.|\n))*-->", "", RegexOptions.Compiled | RegexOptions.Multiline);
responseBody = Regex.Replace(responseBody, @"\r\n?|\n", "", RegexOptions.Compiled | RegexOptions.Multiline);
responseBody = Regex.Replace(responseBody, @"\s+", " ", RegexOptions.Compiled | RegexOptions.Multiline);
if (string.IsNullOrWhiteSpace(responseBody))
responseBody = backup;
} catch
{
responseBody = backup;
}
}
var bytes = Encoding.UTF8.GetBytes(responseBody);
using (var memoryStream = new MemoryStream(bytes))
{
memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(stream);
}
size = bytes.LongLength;
await _stats.UpdateRequestSize(context, size);
}
}
}
finally
{
context.Response.Body = stream;
}
}
}
}
public class HtmlMinificationOptions
{
public string ExcludeFilter { get; set; }
}
namespace CATS.Web.Shared.Infrastructure.Middleware
{
using Microsoft.AspNetCore.Builder;
public class HtmlMinificationPipeline
{
public void Configure(IApplicationBuilder applicationBuilder)
{
applicationBuilder.UseHTMLMinification();
}
}
}
public async Task<string> RenderViewComponent(string viewComponent, object args) {
var sp = HttpContext.RequestServices;
var helper = new DefaultViewComponentHelper(
sp.GetRequiredService<IViewComponentDescriptorCollectionProvider>(),
HtmlEncoder.Default,
sp.GetRequiredService<IViewComponentSelector>(),
sp.GetRequiredService<IViewComponentInvokerFactory>(),
sp.GetRequiredService<IViewBufferScope>());
using (var writer = new StringWriter()) {
var context = new ViewContext(ControllerContext, NullView.Instance, ViewData, TempData, writer, new HtmlHelperOptions());
helper.Contextualize(context);
var result = await helper.InvokeAsync(viewComponent, args);
result.WriteTo(writer, HtmlEncoder.Default);
await writer.FlushAsync();
return writer.
}
}