我正在开始一个新的ASP。. NET Core 6 MVC应用程序,我需要能够唯一地识别所有的html元素,而无需手动插入id属性。我看了看TagHelperComponenets,但这提供了html上下文,因为它是每个请求渲染,而不是在视图编译阶段。
例如:一个剃刀文件的内容是:
<div>
@for(int i = 0; i < 3; i++)
{
<p>Hello world!...</p>
}
</div>
我想把它渲染成
<div id2="somerandomid1">
<p id2="somerandomid2">Hello world!...</p>
<p id2="somerandomid3">Hello world!...</p>
<p id2="somerandomid4">Hello world!...</p>
</div>
这将在整个应用程序中是全局的,并且在请求之间是一致的,即:如果我重新加载页面,它们具有相同的id2s。
我知道我可以手动做到这一点,但我希望能够自动生成它们并插入它们。
更新:密切关注taghelper,我设法创建这个全球标记辅助属性id2补充说,这个问题是发现它生成相同的uniqueid财产所有元素在for循环中,一类是有意义的,因为它写成一个标签在for循环中,虽然过程方法每次调用标记被呈现,我现在添加生成一个id2怎么样?
[HtmlTargetElement("*")]
public class GlobalTagHelper : TagHelper
{
private static readonly string[] avoid = new string[]
{
"html",
"link",
"script",
"head",
"meta",
"title",
};
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (avoid.Contains(context.TagName))
{
return;
}
output.Attributes.Add("id2", context.UniqueId);
}
}
找到解决办法了
这个全局标签助手将在呈现视图和部分时拦截每个标签元素,string[] avoid用于跳过不需要标识的元素,hashids库用于将增量id数转换为长度为10的字符串。
标签助手上下文提供了一个唯一的id,是唯一的元素在razor,即当标签被循环,它将有相同的唯一id,这使得上下文唯一,但不是元素本身,为了解决这个问题,字典用于id2sPerContext记录重复上下文唯一id的数量在相同的httpContext,当它重复计数器递增。
最后,通过使用索引器整数格式化标记助手的唯一id来生成唯一id(名为id2),现在将该字符串添加到静态字典id2s中,增加一个全局整数,然后使用hashids库生成用户友好的代码。
全球标记辅助代码:
[HtmlTargetElement("*")]
public class GlobalTagHelper : TagHelper
{
private static readonly ConcurrentDictionary<string, string> id2s = new();
private static volatile int id2CountGen = 1;
private static readonly ConcurrentDictionary<HttpContext, ConcurrentDictionary<string, int>> id2sPerContext = new();
private const int Id2Length = 10;
private static readonly string[] avoid = new string[]
{
"html",
"link",
"script",
"head",
"meta",
"title",
};
private readonly HttpContext httpContext;
private readonly IHashids hashids;
public GlobalTagHelper(IHttpContextAccessor httpContextAccessor)
{
this.httpContext = httpContextAccessor.HttpContext;
this.hashids = new Hashids(nameof(TestProject), Id2Length);
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (avoid.Contains(context.TagName))
{
return;
}
var uniqueId = context.UniqueId;
if (!id2sPerContext.TryGetValue(httpContext, out var counter))
{
counter = new();
id2sPerContext.TryAdd(httpContext, counter);
}
counter.AddOrUpdate(uniqueId, _ => 1, (_, c) => c + 1);
counter.TryGetValue(uniqueId, out var count);
uniqueId += $"_{count}";
if (!id2s.TryGetValue(uniqueId, out var id2))
{
id2 = GenerateNewId2();
id2s.TryAdd(uniqueId, id2);
}
output.Attributes.Add("id2", id2);
}
private string GenerateNewId2()
{
var id = Interlocked.Increment(ref id2CountGen);
return hashids.Encode(id);
}
}
使用并发字典,因为据我所知标签帮助器是请求的一部分,这是多线程的,我很乐意测试不同的解决方案。