Asp.Net MVC Core内置的标记助手不会处理自定义标记助手提供的属性

时间:2018-12-04 16:32:20

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

出于编写相同样板表格的无聊工作,我想我宁愿写一个标签助手,该助手将产生可以从库存标签助手中处理的属性。但是,即使我设法在上班前先获得我的标签帮手,但仍无法处理我生产的标签帮手。

这是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;
        }
    }
}

任何帮助将不胜感激。 祝你愉快!

1 个答案:

答案 0 :(得分:0)

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