ASP .NET Core — расширение @Html.EditorFor для добавления <span>

Я портирую старое приложение .NET 4.8 на .NET Core, и старое приложение имеет собственный код, который расширяет @Html.EditorFor, чтобы обернуть <input> внутри a, и добавляет <span> после тега <input> (в основном, чтобы добавить знак «%» после ввода поле). Я добавил старый код ниже.

public static MvcHtmlString Addon(this MvcHtmlString htmlText, string text, string classes)
{
    var wrapper = new TagBuilder("div");
    wrapper.AddCssClass("input-group");
    wrapper.AddCssClass(classes);
    wrapper.InnerHtml = htmlText.ToHtmlString();
    var span = new TagBuilder("span");
    span.AddCssClass("input-group-addon");
    span.InnerHtml = text;
    wrapper.InnerHtml += span.ToString();

    return new MvcHtmlString(wrapper.ToString());
}

Приведенный выше код используется вместе с @Html.EditorFor, как показано ниже.

@Html.EditorFor(model => model.PercentageOfControlledSubstances, new { htmlAttributes = new { @class = "form-control short-textfield percent" } }).**Addon**("%", "med-textfield")

При компиляции получаю сообщение об ошибке:

Ссылка на тип «HtmlString» утверждает, что он определен в «System.Web», но его не удалось найти.

Ниже приведен скриншот того, как должен выглядеть окончательный рендеринг.

ASP .NET Core — расширение @Html.EditorFor для добавления &lt;span&gt;

Я знаю, что это преобразование .NET 4.8 в .NET Core, и я искал, как преобразовать мой код, но не смог найти документацию о том, как это сделать в .NET Core. После долгих поисков выяснилось, что .NET Core использует либо IHtmlContent, либо HtmlHelper(s), но я не уверен, так как не могу найти никакой документации.

Я предполагаю, что второстепенный вопрос (и может быть основным) касается ASP.Net Core, следует ли вообще использовать помощники тегов @Html или есть ли лучшее решение для новой платформы?

ChrisW 29.07.2024 17:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Для .NET Core вам необходимо перейти с MvcHtmlString, который поддерживает только .NET Framework MVC, на IHtmlContent.

Реализация почти аналогична, просто нужно перенести следующее:

Нет .NET Framework MVC .NET Core MVC 1 HtmlMvcStringIHtmlContent 2 Добавьте HTML с помощью <Tag Builder instance>.InnerHtml += <HTML string> Добавьте HTML с помощью <Tag Builder instance>.InnerHtml.AppendHtml(<HTML string>) 3 Получить разобранный HTML из Html.Editor() с помощью htmlText Получите проанализированный HTML из Html.Editor() с помощью StringWriter 4 Возвращаемое значение с экземпляром MvcHtmlString Возвращаемое значение с экземпляром HtmlString
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.IO;
using System.Text.Encodings.Web;

public static class HtmlHelperEditorExtensions
{
    public static IHtmlContent Addon(this IHtmlContent htmlContent, string text, string classes)
    {
        var wrapper = new TagBuilder("div");
        wrapper.AddCssClass("input-group");
        wrapper.AddCssClass(classes);

        using (var writer = new StringWriter())
        {
            htmlContent.WriteTo(writer, HtmlEncoder.Default);
            wrapper.InnerHtml.AppendHtml(writer.ToString());
        }

        var span = new TagBuilder("span");
        span.AddCssClass("input-group-addon");
        span.InnerHtml.AppendHtml(text);

        wrapper.InnerHtml.AppendHtml(span);

        using (var writer = new StringWriter())
        {
            wrapper.WriteTo(writer, HtmlEncoder.Default);
            return new HtmlString(writer.ToString());
        }
    }
}

У меня было готово то же самое решение, но я искал сообщение, которое проверяло декларацию записи строк без using(). StringWriter writer = new(); работает как альтернатива. Голосую за ответ из-за великолепной таблицы, обобщающей миграцию.

Dave B 30.07.2024 03:30

Работал отлично.

ChrisW 30.07.2024 05:50

Чтобы ответить на ваш комментарий в исходном сообщении:

Я предполагаю, что второстепенный вопрос (и может быть основным) касается ASP.Net Core, следует ли вообще использовать помощники тегов @Html или есть ли лучшее решение для новой платформы?

вр; доктор

ASP.NET Core представил Помощники тегов в качестве альтернативы помощникам HTML (но «не заменяйте помощники HTML»). Помощники тегов улучшают читаемость, могут помочь уменьшить количество ошибок в кодировании и «создать более надежный, надежный и удобный в сопровождении код».

<input asp-for = "PercentageOfControlledSubstances"
   class = "form-control short-textfield percent" 
   data-addon-text = "%" data-addon-class = "med-textfield" />

Приведенный выше InputTagHelper HTML эквивалентен @Html.EditorFor HTML Helper из исходного кода .NET Framework 4.8 в вашем сообщении.

@Html.EditorFor(model => model.PercentageOfControlledSubstances, new { htmlAttributes = new { @class = "form-control short-textfield percent" } }).Addon("%", "med-textfield")

Наряду с соответствующими методами переопределения расширений (в сообщении @YongShun для HTML Helper и ниже в этом сообщении для Tag Helper) создается один и тот же вывод HTML:

<div class = "input-group med-textfield">
    <input aria-label = "Percentage of controlled substances" class = "form-control short-textfield percent text-box single-line" id = "PercentageOfControlledSubstances" name = "PercentageOfControlledSubstances" title = "Percentage of controlled substances" type = "text">
    <span class = "input-group-addon">%</span>
</div>

Добавление aria-, title или любых других атрибутов.

Атрибуты в EditorFor HTML Helper в исходном сообщении не включают атрибут title или атрибуты aria-, которые Chrome DevTools называет проблемой доступности. Этот ТАК пост дает представление об использовании одного или другого или обоих.

Добавление этих атрибутов в EditorFor HTML Helper:

@Html.EditorFor(model => model.PercentageOfControlledSubstances, new { htmlAttributes = new { @class = "form-control short-textfield percent", title = "Percentage of controlled substances", aria_label = "Percentage of controlled substances" } }).Addon("%", "med-textfield")

Длина помощника @Html.EditorFor() становится намного больше. Также обратите внимание, что атрибуты, в названии которых есть дефис (-) (например, aria-label), должны заменяться тире подчеркиванием (например, aria_label).

Добавление новых атрибутов в вспомогательный элемент тега ввода — это, конечно, просто добавление атрибутов к элементам HTML:

<input asp-for = "PercentageOfControlledSubstances"
   class = "form-control short-textfield percent" 
   title = "Percentage of controlled substances"
   aria-label = "Percentage of controlled substances"
   data-addon-text = "%" data-addon-class = "med-textfield" />

Process переопределить расширение

Подобно классу HtmlHelperEditorExtensions в ответе @YongShun, вспомогательные функции тегов обеспечивают переопределение процесса путем реализации интерфейса ITagHelper в объявлении класса.

В приведенном выше помощнике по вкладкам input атрибут data-addon-text запускает метод переопределения, который заменит исходный HTML дополнительным HTML.

Следующий атрибут [HtmlTargetElement] в классе расширения устанавливает условия для выполнения метода переопределения Process: Тег <input>, содержащий атрибут data-addon-text.

[HtmlTargetElement("input", Attributes = "data-addon-text")]
public class AddonAttributeTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        ...
    }
}

Аддонатрибутетагхелпер.cs

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace WebApplication1.Helpers
{
    // Add the following to the file '_ViewImports.cshtml' in the
    // 'Pages' folder or add the following line to the top of the
    // Razor page that contains an '<input>' tag with the custom
    // data attribute 'data-addon-text'.
    // @addTagHelper WebApplication1.Helpers.AddonAttributeTagHelper, WebApplication1

    [HtmlTargetElement("input", Attributes = "data-addon-text")]
    public class AddonAttributeTagHelper : TagHelper
    {
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            // Get addon text
            output.Attributes.TryGetAttribute("data-addon-text", out TagHelperAttribute addonTextAttr);
            if (string.IsNullOrWhiteSpace(addonTextAttr.Value.ToString())) { return; }
            string? addonText = addonTextAttr.Value.ToString();

            // Get addon class name(s)
            output.Attributes.TryGetAttribute("data-addon-class", out TagHelperAttribute addonClassAttr);
            string? addonClass = string.IsNullOrWhiteSpace(addonClassAttr?.Value?.ToString()) ? "" : addonClassAttr?.Value.ToString();

            // Remove 'data-addon-' attributes before retrieving original HTML
            output.Attributes.Remove(addonTextAttr);
            output.Attributes.Remove(addonClassAttr);

            // Write original HTML to 'origHmtl' variable
            StringWriter writer = new();
            output.WriteTo(writer, System.Text.Encodings.Web.HtmlEncoder.Default);
            string origHtml = writer.ToString();

            // Set addon HTML using original HTML, addon class name, and addon text
            string addonHtml = $"<div class='input-group {addonClass}'>{origHtml}<span class='input-group-addon'>{addonText}</span></div>";

            // Replace original tag with contents of 'addonHtml' variable
            // https://stackoverflow.com/questions/43463145/custom-tag-helper-replace-the-html-tag
            output.TagName = null;
            output.TagMode = TagMode.StartTagAndEndTag;
            output.PostContent.SetHtmlContent(addonHtml);
        }
    }
}

Страница бритвы

@page
@model WebApplication1.Pages.ExtendingHtmlEditorForModel
@using WebApplication1.Helpers;
@addTagHelper WebApplication1.Helpers.AddonAttributeTagHelper, WebApplication1

<p>Extending Html.EditorFor to append span</p>

@Html.EditorFor(model => model.PercentageOfControlledSubstances, new { htmlAttributes = new { @class = "form-control short-textfield percent", title = "Percentage of controlled substances", aria_label = "Percentage of controlled substances" } }).Addon("%", "med-textfield")

<p>Tag Helper</p>

<input asp-for = "PercentageOfControlledSubstances"
       class = "form-control short-textfield percent" 
       title = "Percentage of controlled substances"
       aria-label = "Percentage of controlled substances"
       data-addon-text = "%" data-addon-class = "med-textfield" />

Обработка ошибок

Приведенный выше метод переопределения Process обрабатывает следующие случаи: пустой текст для атрибута класса надстройки; пустой текст для дополнительного текстового атрибута; отсутствует дополнительный текстовый атрибут. В последнем случае метод переопределения Process никогда не вызывается, поскольку элемент HTML не соответствует условию:

[HtmlTargetElement("input", Attributes = "data-addon-text")]

в классе расширения.

<input asp-for = "PercentageOfControlledSubstances"
       class = "form-control short-textfield percent" 
       data-addon-text = "%" data-addon-class = "" />

<input asp-for = "PercentageOfControlledSubstances"
       class = "form-control short-textfield percent" 
       data-addon-text = "" data-addon-class = "med-textfield" />

<input asp-for = "PercentageOfControlledSubstances"
       class = "form-control short-textfield percent" 
       data-addon-class = "med-textfield" />

Документация

Из документации Microsoft для Помощников тегов в ASP.NET Core:

Вспомогательные функции тегов позволяют серверному коду участвовать в создании и отображении HTML-элементов в файлах Razor. ... Если вы знакомы со вспомогательными средствами HTML, вспомогательные функции тегов уменьшают явные переходы между HTML и C# в представлениях Razor. Во многих случаях помощники HTML предоставляют альтернативный подход к конкретному помощнику тега, но важно понимать, что помощники тега не заменяют помощники HTML, и для каждого помощника HTML не существует помощника тега. Помощники тегов по сравнению с помощниками HTML объясняют различия более подробно.

Под заголовком «Что предоставляют помощники тегов» в той же документации, указанной выше, Microsoft перечисляет следующие преимущества:

Опыт разработки с поддержкой HTML. По большей части разметка Razor с использованием вспомогательных функций тегов выглядит как стандартный HTML. Дизайнеры внешнего интерфейса, знакомые с HTML/CSS/JavaScript, могут редактировать Razor, не изучая синтаксис C# Razor.

В вашем посте редактором свойства PercentageOfControlledSubstances является элемент <input>.

элемент ... содержит атрибут asp-for. Этот атрибут извлекает имя указанного свойства модели в отображаемый HTML.

В документации представлена ​​информация по сравнению вспомогательных функций тегов и вспомогательных функций HTML здесь.

В этом документе подробно описывается создание метода переопределения Process, аналогичного методу Process, указанному выше.

Другие вопросы по теме

Похожие вопросы

Netwonsoft JsonConvert.Deserialization выдает исключение JsonSerializationException: «Ошибка преобразования значения «Имя моего пользовательского объекта» в тип «System.Type»
Как обеспечить автоматическое масштабирование для CollectionView в объекте Popup из CommunityToolkit.Maui после его заполнения с помощью события нажатия кнопки на платформе Windows?
Перенаправление вызова .NET Core OIDC не работает с интерфейсом Angular
Как добавить несколько веб-приложений Blazor в существующий веб-API
Веб-приложение .Net 8 Blazor (сервер) -> Начните с языка браузера и разрешите пользователю менять язык через раскрывающийся список
Что означает этот вариант значка проекта CsProj в обозревателе решений Visual Studio 2022?
Передача массива объектов из C# в VBA Excel
Как я могу читать статические свойства из экземпляров классов?
Остановить выполнение приложения при закрытии формы C#
Для оптимизации кода есть любой способ избежать использования нескольких операторов OR(||) в одной строке кода