【问题标题】:Asp.Net MVC Core built-in tag helpers won't process attributes provided from custom taghelpersAsp.Net MVC Core 内置标签助手不会处理自定义标签助手提供的属性
【发布时间】:2018-12-05 00:44:39
【问题描述】:

由于编写相同的样板表单感到无聊,我想我宁愿编写一个标签助手,它可以生成可以从库存标签助手处理的属性。但是,即使我在工作之前设法在表单标签助手之前获得了我的标签助手,表单标签助手也不会处理我生成的那些。

这是cshtml:

@model City

@{
    Layout = "_Layout";
    ViewData["Title"] = "Create City";
}

<form method="post" asp-action="Create">
    @foreach (string propName in BaseModel.GetProperties<City>()) {
        <formgroup for="@propName" />
    }

    <div class="form-group">
        <label asp-for="Name">Name:</label>
        <input class="form-control" asp-for="Name" />
    </div>
    <div class="form-group">
        <label asp-for="Country">Country:</label>
        <input class="form-control" asp-for="Country" />
    </div>
    <div class="form-group">
        <label asp-for="Population">Population:</label>
        <input class="form-control" asp-for="Population" />
    </div>
    <button type="submit" class="btn btn-primary">Create</button>
    <a class="btn btn-secondary" asp-controller="Home" asp-action="Index">Cancel</a>
</form>

这是输出:

<form method="post" action="/City/Create">
        <div class="form-group"><label asp-for="Name"></label><input asp-for="Name" class="form-control"></div>
        <div class="form-group"><label asp-for="Country"></label><input asp-for="Country" class="form-control"></div>
        <div class="form-group"><label asp-for="Population"></label><input asp-for="Population" class="form-control"></div>

    <div class="form-group">
        <label for="Name">Name:</label>
        <input class="form-control" type="text" id="Name" name="Name" value="">
    </div>
    <div class="form-group">
        <label for="Country">Country:</label>
        <input class="form-control" type="text" id="Country" name="Country" value="">
    </div>
    <div class="form-group">
        <label for="Population">Population:</label>
        <input class="form-control" type="number" data-val="true" data-val-required="The Population field is required." id="Population" name="Population" value="">
    </div>
    <button type="submit" class="btn btn-primary">Create</button>
    <a class="btn btn-secondary" href="/">Cancel</a>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8M_6usK6CRRNkwluTiTW8uaAAfhMcU9tAxyCT7z55zQKmpUwpi_lfSDIN4FrlMo9cE3Ka9zgX4WdpXHUdlBFVGsLIw7h_cR3FjJb6Vjqnjm8mQmtKTey_9l188p9E2sKgiksO_OB6K9-F1D7SP2lX0g"></form>

这是我的标签助手:

using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;

namespace ViewComponents.Infrastructure.TagHelpers {
    [HtmlTargetElement("formgroup", Attributes = "for", TagStructure = TagStructure.NormalOrSelfClosing)]
    public class FormGroupTagHelper : TagHelper {

        /// <inheritdoc />
        public override int Order => -2000;

        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext { get; set; }

        protected IHtmlGenerator Generator { get; }

        public string For { get; set; }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) {
            if (context == null) {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null) {
                throw new ArgumentNullException(nameof(output));
            }

            // So that other tag helpers are processed after me...
            var childContent = await output.GetChildContentAsync();

            // Starting up...
            // Replace the tag name, include the form-group bootstrap class.

            output.TagName = "div";
            output.TagMode = TagMode.StartTagAndEndTag;
            output.Attributes.Add("class", "form-group");

            PropertyInfo propInfo = ViewContext.ViewData.ModelMetadata.ModelType.GetTypeInfo().GetDeclaredProperty(For);
            output.Content.AppendHtml(GenerateLabel(new Dictionary<string, string> { ["asp-for"] = propInfo.Name }));
            output.Content.AppendHtml(GenerateInput(new Dictionary<string, string> { ["asp-for"] = propInfo.Name, ["class"] = "form-control" }));
        }

        public static IHtmlContent GenerateLabel(IReadOnlyDictionary<string, string> attrDict) {
            TagBuilder tBuilder = new TagBuilder("label");
            foreach (var kvp in attrDict)
                tBuilder.Attributes.Add(kvp);
            return tBuilder;
        }

        public static IHtmlContent GenerateInput(IReadOnlyDictionary<string, string> attrDict) {
            TagBuilder tBuilder = new TagBuilder("input");
            foreach (var kvp in attrDict)
                tBuilder.Attributes.Add(kvp);
            return tBuilder;
        }
    }
}

任何帮助将不胜感激。 祝你好运!

【问题讨论】:

    标签: asp.net-mvc asp.net-core-2.1 asp.net-core-tag-helpers


    【解决方案1】:

    标签助手不是按特定顺序处理的,因此您不能指望一个能够根据另一个的输出来做某事。每个标签助手都需要设计为独立于任何其他标签助手,因此如果您需要呈现 HTML,则需要在标签助手中自己处理。但是,由于您试图让一个标签生成任何类型的表单字段,这将是一项繁重的工作。这基本上超出了标签助手的范围。

    【讨论】:

    • 您好,谢谢您的回复,但我认为您根据here 弄错了。我对此持怀疑态度,我试了一下,taghelpers 确实按指定的顺序执行。但我认为他们可能会在自己的范围内被调用,使得 taghelper 的输出不会成为另一个 taghelper 的输出,不包括通过 TagHelperContext.Items 字典在它们之间传递数据的情况。
    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 2019-11-07
    相关资源
    最近更新 更多