Asp.net Core Razor 页面 - 自定义 TagHelpers 和样板 CRUD 代码

问题描述 投票:0回答:1

我确信这个问题以前已经遇到过很多次了。

我有很多 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);
}
c# asp.net-core razor-pages asp.net-core-tag-helpers
1个回答
0
投票

这是您可以遵循的完整工作演示:

创建自定义标签助手

[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" />
}
© www.soinside.com 2019 - 2024. All rights reserved.