我确信这个问题以前已经遇到过很多次了。
我有很多 CRUD 表单,所以我有很多重复的样板代码。
例如
<div class="form-group">
<label asp-for="MyModel.Property1" class="control-label"></label>
<input asp-for="MyModel.Property1" class="form-control" />
<span asp-validation-for="MyModel.Property1" class="text-danger"></span>
</div>
上述代码针对每个属性、每个表单一次又一次地重复。看起来总是一样的(例如,如果它是一个下拉菜单)。
我已经成功地使用 EditorTemplates 获得了可重复运行的东西,但这感觉很笨拙。我需要每个属性类型等不同的模板。 这需要运行: @Html.EditorFor(m => m.MyModel.Property1, "_MyString") 我觉得@Html。在 Razor Pages 中几乎不鼓励,解决方案应该在其他地方。
我花了太长时间寻找自定义 TagHelper 设置和工作,但我认为这是不可能的。您可以创建自己的 TagHelpers 并使用 TagBuilder,但是您会丢失 InputTagHelper 等内部的所有逻辑。 https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.TagHelpers/src/InputTagHelper.cs
它需要利用输入和标签标签助手,因为有很多逻辑,例如根据上面的链接,输入标签助手中的属性类型。您似乎无法使用这些。
我正在寻找一种真正通用的方法来减少我的样板代码,并希望可能有灵丹妙药?
编辑说 - 您过去也可以在 MVC 中执行此操作,但您无法通过 Razor Pages 执行此操作,而无需创建每个模型。
public static IHtmlContent MyEditorFor<TModel, TResult>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TResult>> expression,
string templateName = "MyDefaultTemplateName")
{
return htmlHelper.EditorFor(expression, templateName);
}
这是您可以遵循的完整工作演示:
创建自定义标签助手
[HtmlTargetElement("div-group", Attributes = "asp-for")]
public class DivGroupTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
private IHtmlGenerator _htmlGenerator;
public DivGroupTagHelper(IHtmlGenerator htmlGenerator)
{
_htmlGenerator = htmlGenerator;
}
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
[HtmlAttributeName("class")]
public string CssClass { get; set; }
[HtmlAttributeName("label-class")]
public string LabelCssClass { get; set; }
[HtmlAttributeName("input-class")]
public string InputCssClass { get; set; }
[HtmlAttributeName("validation-class")]
public string ValidationCssClass { get; set; }
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.Attributes.SetAttribute("class", "form-group " + CssClass);
// Create a context and output for the label
var labelContext = new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), Guid.NewGuid().ToString("N"));
var labelOutput = new TagHelperOutput("label", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
var labelTagHelper = new LabelTagHelper(_htmlGenerator)
{
For = For,
ViewContext = ViewContext
};
await labelTagHelper.ProcessAsync(labelContext, labelOutput);
labelOutput.AddClass("control-label", HtmlEncoder.Default);
if (!string.IsNullOrEmpty(LabelCssClass)) labelOutput.AddClass(LabelCssClass, HtmlEncoder.Default);
//Create a context and output for the input
var inputContext = new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), Guid.NewGuid().ToString("N"));
var inputOutput = new TagHelperOutput("input", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
var inputTagHelper = new InputTagHelper(_htmlGenerator)
{
For = For,
ViewContext = ViewContext
};
await inputTagHelper.ProcessAsync(inputContext, inputOutput);
inputOutput.AddClass("form-control", HtmlEncoder.Default);
if (!string.IsNullOrEmpty(InputCssClass)) inputOutput.AddClass(InputCssClass, HtmlEncoder.Default);
// Create a context and output for the validation message
var validationContext = new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), Guid.NewGuid().ToString("N"));
var validationOutput = new TagHelperOutput("span", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
var validationTagHelper = new ValidationMessageTagHelper(_htmlGenerator)
{
For = For,
ViewContext = ViewContext
};
await validationTagHelper.ProcessAsync(validationContext, validationOutput);
validationOutput.AddClass("text-danger", HtmlEncoder.Default);
if (!string.IsNullOrEmpty(ValidationCssClass)) validationOutput.AddClass(ValidationCssClass, HtmlEncoder.Default);
// Append the generated content to the output
output.Content.AppendHtml(labelOutput);
output.Content.AppendHtml(inputOutput);
output.Content.AppendHtml(validationOutput);
}
}
在您的
_ViewImports.cshtml
文件中添加 Tag Helper 注册
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, YourNamespace
在 Razor 页面中使用自定义标签帮助程序
@page
@model IndexModel
<form method="post">
<div-group asp-for="Password"></div-group>
<div-group asp-for="Email"></div-group>
<input type="submit" value="Create"/>
</form>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}