Как получить ненавязчивую проверочную разметку в моем помощнике по настраиваемым тегам

Есть ли простой способ в помощнике настраиваемого тега ASP.Net Core получить разметку HTML, которая была бы сгенерирована помощником тега <span asp-validation-for="xxx">?

Другими словами, могу ли я получить что-то эквивалентное HtmlHelper.ValidationMessageFor() в моем помощнике по тегам? Или мне нужно воссоздать это самому, покопавшись в свойствах ModelExpression.ModelMetadata?

Фон:

Я создал помощники тегов, которые добавляют разметку Bootstrap вокруг общих элементов HTML, таких как <input>, <button> и т. Д. Помимо добавления разметки Bootstrap, эти помощники тегов также добавляют ненавязчивую разметку проверки после элементов «input»:

<span class='field-validation-valid' data-valmsg-for='{name}' data-valmsg-replace='true'></span>

Это отлично подходит для проверки на стороне клиента, потому что JavaScript видит атрибуты data- * и делает свое дело. Но это не работает для проверки на стороне сервера. Если валидатор на стороне сервера возвращает сообщение об ошибке, это сообщение не отображается в форме.

Небольшое экспериментирование показывает, что помощник тега <span asp-validation-for="xxx"> (который я НЕ использую) работает с валидаторами на стороне сервера для изменения HTML-кода, отправляемого клиенту, если связанная переменная модели имеет ошибку проверки. Измененный HTML-код содержит сообщение об ошибке, предоставленное валидатором:

<span class='field-validation-error' data-valmsg-for='{name}' data-valmsg-replace='true'>Some error message.</span>

Итак, мои помощники по тегам должны делать то же самое и выдавать нормальную разметку или сообщение об ошибке.

Было бы очень просто, если бы мой помощник тега мог испускать элемент <span asp-validation-for="xxx">, но, насколько я могу судить, нет способа заставить HTML, созданный моим помощником тега, интерпретироваться как помощники тега.

Я могу копаться в метаданных модели и обнаруживать сообщение об ошибке и соответствующим образом форматировать тег <span> сообщения проверки, но вся эта работа уже сделана за меня (и, вероятно, более правильно, чем я мог бы это сделать) HtmlHelper.ValidationMessageFor() и тегом validation-for span помощник.

FWIW, эта статья демонстрирует волшебство, которое позволяет помощнику тега получить доступ к HtmlHelper. Я бы предпочел избежать этого пути и использовать что-то, что больше похоже на собственный код "помощника по тегам", если смогу.


person Bob.at.Indigo.Health    schedule 23.03.2020    source источник


Ответы (1)


Если у вас все еще есть эта проблема, мне удалось достичь желаемой функциональности, перепрофилировав существующий ValidationMessageTagHelper в собственном TagHelper. Если вы обязательно вызовете метод ProcessAsync для ValidationMessageTagHelper, как в этой строке:

await validation.ProcessAsync(validationContext, validationOutput);

Это сделает проверку, которую вы ожидали, с помощью проверки на стороне сервера из ViewData. Мой помощник настраиваемого тега проверки, который работал с проверкой на стороне сервера, выглядел так:

[HtmlTargetElement("validation")]
public class CustomValidationTagHelper : TagHelper
{
    private IHtmlGenerator _htmlGenerator;

    public CustomValidationTagHelper(IHtmlGenerator htmlGenerator)
    {
        _htmlGenerator = htmlGenerator;
    }

    [HtmlAttributeName("asp-for")]
    public ModelExpression For { get; set; }

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

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {

        var validationContext = CreateTagHelperContext();
        var validationOutput = CreateTagHelperOutput("span");

        var validation = new ValidationMessageTagHelper(_htmlGenerator)
        {
            For = For,
            ViewContext = ViewContext,

        };

        await validation.ProcessAsync(validationContext, validationOutput);
        validationOutput.Attributes.SetAttribute("class", "field-validation-error text-danger");

        output.TagName = "";


        output.Content.AppendHtml(validationOutput);
    }

    private static TagHelperContext CreateTagHelperContext()
    {
        return new TagHelperContext(
            new TagHelperAttributeList(),
            new Dictionary<object, object>(),
            Guid.NewGuid().ToString("N"));
    }

    private static TagHelperOutput CreateTagHelperOutput(string tagName)
    {
        return new TagHelperOutput(
            tagName,
            new TagHelperAttributeList(),
            (a, b) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent(string.Empty);
                return Task.FromResult<TagHelperContent>(tagHelperContent);
            });
    }
}

и используется на странице так:

<validation asp-for="Username" />
person ClintM    schedule 29.03.2021