В компоненте представления, вызываемом как помощник тега, как мы можем получить доступ к внутреннему HTML?
В помощниках по тегам мы можем получить доступ к тегам внутри HTML.
<!-- Index.cshtml -->
<my-first>
This is the original Inner HTML from the *.cshtml file.
</my-first>
// MyFirstTagHelper.cs > ProcessAsync
var childContent = await output.GetChildContentAsync();
var innerHtml = childContent.GetContent();
Если мы вызовем компонент представления в качестве помощника по тегам, как мы можем получить доступ к внутреннему HTML?
<vc:my-first>
This is the original Inner HTML from the *.cshtml file.
</vc:my-first>
// MyFirstViewComponent.cs > InvokeAsync()
var innerHtml = DoMagic();
Несколько дальнейших мыслей:
Я ценю, что мы можем передавать произвольный контент компоненту представления через атрибуты HTML. Это может стать непрактичным, однако, в случае очень большого количества текста, и в этом случае внутренний HTML будет более читабельным и будет иметь лучшую поддержку инструментов.
Некоторые могут также сказать: "Почему бы тогда просто не использовать помощник по тегам?" Что ж, мы хотим связать представление с помощником тега, а помощники тега не поддерживают представления; вместо этого, помощники по тегам требуют, чтобы мы строили весь HTML программно.
Так что мы застряли в тесноте. С одной стороны, нам нужен помощник по тегам, но они не поддерживают представления; с другой стороны, мы можем использовать компонент представления в качестве помощника по тегам, но компоненты представления могут не позволить нам получить доступ к внутреннему HTML.
2 ответа
Извините, но ответ "Просто используйте помощник по тегам"
Смотрите следующую проблему: https://github.com/aspnet/Mvc/issues/5465
Будучи в состоянии призвать ViewComponent
из помощника тега это просто другой способ вызвать его вместо использования @Component.Invoke()
,
Я вижу, где это вводит в заблуждение, и я вспоминаю, как видел в руководствах по ASP.NET Core 2.1 заявление о том, что "View Components похожи на Tag Helpers, но более мощны".
Наконец-то появился способ получить наш торт и съесть его! Разрешить вспомогательному тегу использовать представление Razor в качестве источника HTML, но по-прежнему обертывать разметку при использовании на странице Razor.
Используйте помощник тегов, чтобы получить внутренний HTML в виде строки. Затем напрямую задействуйте механизм представления Razor для рендеринга частичного представления в строку. Наконец, используйте замену строки, чтобы поместить внутреннюю строку HTML в нужное место в строке частичного представления.
Ключевым моментом является использование высококачественных ответов StackOverflow, доступных при рендеринге представления Razor в виде строки. См. службу IRazorViewToStringRenderer здесь (здесь написано ASP.NET Core 3.1, но у меня работало в версии 2.2) или в другом месте как Mvc.RenderViewToString.
Тег-помощник:
// RazorViewTagHelper.cs
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace GetSafetyCone.TagHelpers
{
public class RazorViewTagHelper : TagHelper
{
private IRazorViewToStringRenderer RazorViewToStringRenderer { get; }
public ViewName { get; set; }
public RazorViewedTagHelperBase(
IRazorViewToStringRenderer razorViewToStringRenderer)
{
this.RazorViewToStringRenderer = razorViewToStringRenderer;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
var childContentString = childContent.GetContent();
var viewHtmlTemplateString = await this.RazorViewToStringRenderer.Render<object>(this.ViewName, null);
var viewHtmlString = viewHtmlTemplateString.Replace("BODY_GOES_HERE", childContentString);
output.Content.SetHtmlContent(viewHtmlString); // Set the content.
}
}
}
Частичное представление, которое вы хотите использовать в качестве источника HTML для вспомогательного тега:
// ViewXYZ.cshtml
@*
ViewXYZ to be rendered to string.
*@
// No model specified, so ok model was a null object.
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-3xl mx-auto">
BODY_GOES_HERE
</div>
</div>
И вот tag-helper в использовании:
// YourPage.cshtml
<razor-view view-name="ViewXYZ">
<p>You should see this content wrapped in the ViewXYZ divs.</p>
</razor-view>
Если вы хотите, вы можете упростить замену строки и использовать тег childContent TagHelperContent непосредственно в качестве модели представления:
// RazorViewTagHelper.cs
...
var childContent = await output.GetChildContentAsync();
var viewHtmlString = await this.RazorViewToStringRenderer.Render("viewName", childContent);
...
// ViewXYZ.cshtml
...
@model Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContent;
...
<div class="max-w-3xl mx-auto">
@(this.Model)
</div>
...