提问人:nfplee 提问时间:7/25/2023 最后编辑:nfplee 更新时间:7/27/2023 访问量:88
ASP.NET Core:检测标记帮助程序是否与父元素一起呈现
ASP.NET Core: Detect whether a tag helper is rendered with a parent element
问:
在 ASP.NET Core 中,是否可以检测标记帮助程序是否使用父元素呈现?
我问的原因是我有一个脚本标签帮助程序,它缓存了它通常会呈现的 HTML,而是我使用中间件在结束 body 标签之前呈现 HTML。但是,如果在部分视图中调用标记帮助程序,那么我想简单地将其呈现到位。
我的第一个想法是添加一个正文标签帮助程序,然后将一个变量添加到请求缓存中,我可以在我的脚本标记帮助程序中检测到该变量。但是,我发现由于正文标签帮助程序位于我的布局页面中,因此它是在我的视图(执行脚本标记帮助程序)之后呈现的。
我想到的另一种解决方案是在操作中存储一个变量,但我不喜欢这样,因为每次返回部分视图时都必须记住这样做。
我将不胜感激任何帮助。
编辑:这里有一些代码供参考。
ScriptTagHelper:
public class ScriptTagHelper : TagHelper {
private readonly IHtmlManager _htmlManager;
public ScriptTagHelper(IHtmlManager htmlManager) {
_htmlManager = htmlManager;
}
public string? At { get; set; }
[HtmlAttributeNotBound, ViewContext]
public ViewContext ViewContext { get; set; } = default!;
public override void Process(TagHelperContext context, TagHelperOutput output) {
if (!string.IsNullOrEmpty(At)) {
output.SuppressOutput();
var builder = new TagBuilder("script") {
TagRenderMode = TagRenderMode.Normal
};
foreach (var attribute in output.Attributes) {
builder.Attributes.Add(attribute.Name, attribute.Value.ToString());
}
_htmlManager.RegisterHtml(At, builder);
}
}
}
这是我的中间件:
public class RenderHtmlMiddleware {
private readonly RequestDelegate _next;
public RenderHtmlMiddleware(RequestDelegate next) {
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext, IHtmlManager htmlManager) {
var originBody = httpContext.Response.Body;
using var body = new MemoryStream();
httpContext.Response.Body = body;
try {
await _next(httpContext);
} finally {
httpContext.Response.Body = originBody;
}
if (body.Length > 0) {
var content = Encoding.UTF8.GetString(body.ToArray());
foreach (var position in Enum.GetValues<HtmlPosition>()) {
var html = await htmlManager.GetHtmlAsync(position);
var innerHtml = string.Join("", html.Select(h => h.ToHtmlString()));
... Code removed for brevity which handles different positions
content = content.Replace("</body>", string.Concat(innerHtml, Environment.NewLine, "</body>"));
}
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(content);
await httpContext.Response.WriteAsync(content);
}
}
}
现在在我的视图/部分视图中,我可以简单地说:
<script at="@HtmlPosition.BodyPostContent" src="foo"></script>
答:
0赞
Ruikai Feng
7/26/2023
#1
但是,如果在部分视图中调用标记帮助程序,那么我会 喜欢简单地将其渲染到位。
如果您只想检查它是否在 partialview 中呈现:
您可以添加一个属性:
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
您可以使用 ViewContext 访问 HttpContext/当前视图名称
一个最小的例子:
[HtmlTargetElement("MyTag")]
public class MyTag : TagHelper
{
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "label";
//check if is partial
var path = ViewContext.View.Path;
var ispartial = path.Contains("Partial");
if (!ispartial)
{
output.SuppressOutput();
}
}
}
在“主页”视图中:
<partial name="MyPartial"/>
<MyTag>Home</MyTag>
在部分视图中:
<MyTag>Partial</MyTag>
结果:
仅被渲染<label>partial</label>
更新: 模板的可能解决方案:
public class MyPartial : PartialTagHelper
{
public MyPartial(ICompositeViewEngine viewEngine, IViewBufferScope viewBufferScope) : base(viewEngine, viewBufferScope)
{
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
this.ViewContext.HttpContext.Items.Add("IsPartial", true);
await base.ProcessAsync(context, output);
this.ViewContext.HttpContext.Items.Remove("IsPartial");
}
}
[HtmlTargetElement("MyTag")]
public class MyTag : TagHelper
{
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
public ViewLocationExpanderContext ViewLocationExpanderContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "label";
var ispartial = ViewContext.HttpContext.Items.TryGetValue("IsPartial",out var partial);
//access httpcontext
if (!ispartial)
{
output.SuppressOutput();
}
}
}
在视野中:
@model MyEntity
<my-partial name="MyPartial"model="@Model"/>
@Html.DisplayFor(x=>x.SomeEntity)
部分:
@model MyEntity
@Html.DisplayFor(x=>x.SomeEntity)
模板:
@model SomeEntity
<dl>
<dd>Id:@Model.Id</dd>
<dd>Amount:@Model.Amount</dd>
<dd>Rate:@Model.Rate</dd>
</dl>
<MyTag>InPartial1</MyTag>
<MyTag>InPartial2</MyTag>
即使 taghelper 是在模板中调用的,也只呈现了部分视图中的那个:
评论
0赞
nfplee
7/26/2023
谢谢,我唯一的问题是部分视图可能会调用显示/编辑器模板,该模板本身调用脚本标签帮助程序。因此,如何确定是在局部视图还是标准视图中调用了显示/编辑器模板?
0赞
Ruikai Feng
7/26/2023
嗨,@nfplee您能分享任何相关的代码吗?您是否正在尝试使用 Html.Displayfor/Html.EditorFor ?
0赞
nfplee
7/26/2023
我用一些示例代码更新了我的问题。
0赞
Ruikai Feng
7/27/2023
我已经更新了我的答案,请检查一下
0赞
Ruikai Feng
7/27/2023
创建自定义 partialview 标签助手可以解决您的问题
评论