You can achieve this goal by customizing taghelper.
Example:

RequiredTagHelper:
namespace WebApplication5.TagHelpers
{
[HtmlTargetElement("label", Attributes = ForAttributeName)]
public class RequiredTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (output == null)
throw new ArgumentNullException(nameof(output));
if (For.Metadata.IsRequired)
{
var existingClass = output.Attributes.FirstOrDefault(f => f.Name == "class");
var cssClass = string.Empty;
if (existingClass != null)
{
cssClass = $"{existingClass.Value} ";
}
cssClass += "required";
output.Attributes.SetAttribute("class", cssClass);
}
}
}
}
Then in your _ViewImports.cshtml
,add:
@addTagHelper *, WebApplication5(your project name)
Css:
.required:after {
content: "*";
font-weight: bold;
color: red;
}
View:
<label asp-for="Name"></label>
<input asp-for="Name" />
<label asp-for="Age"></label>
<input asp-for="Age" />
Test result:

In this case,when you use <label asp-for="xx"></label>
, it will check if your attribute is required, if it is required, then it will add *.