C# 是否可以在控制器内执行ViewComponent并将HTML存储为字符串

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 一种方

我目前有几个视图组件,在许多不同的地方使用。我希望能够将调用视图组件时生成的HTML存储到字符串变量中,以便将HTML用于其他用途(如电子邮件)

我看了一些问题和帖子,但没有找到一个符合我要求的。我当前存储了ViewComponentResult以供使用,但ExecuterResult()返回void,因此无法使用它

我希望能够操作视图组件结果以执行,然后返回将发送到浏览器以显示的HTML。然后我可以用它作为电子邮件正文。但是,在不知道结果视图的完整路径的情况下,我目前还无法获得HTML

一种方法是制作“您自己的”html标记(更像是现有html上的扩展方法)并实现

您可以在重写时访问或更改内容,我有一个类,它扩展了几个html标记来管理custome全球化,请查看代码,看看这是否对您有所帮助

在您的页面中,您可以通过添加属性“拥有”html,就像我在这里用我的属性cats语言键演示的那样:

<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.
  }
}