Я портирую старое приложение .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», но его не удалось найти.
Ниже приведен скриншот того, как должен выглядеть окончательный рендеринг.
Я знаю, что это преобразование .NET 4.8 в .NET Core, и я искал, как преобразовать мой код, но не смог найти документацию о том, как это сделать в .NET Core. После долгих поисков выяснилось, что .NET Core использует либо IHtmlContent
, либо HtmlHelper(s), но я не уверен, так как не могу найти никакой документации.
Для .NET Core вам необходимо перейти с MvcHtmlString
, который поддерживает только .NET Framework MVC, на IHtmlContent
.
Реализация почти аналогична, просто нужно перенести следующее:
HtmlMvcString
IHtmlContent
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();
работает как альтернатива. Голосую за ответ из-за великолепной таблицы, обобщающей миграцию.
Работал отлично.
Чтобы ответить на ваш комментарий в исходном сообщении:
Я предполагаю, что второстепенный вопрос (и может быть основным) касается 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
, указанному выше.
Я предполагаю, что второстепенный вопрос (и может быть основным) касается ASP.Net Core, следует ли вообще использовать помощники тегов @Html или есть ли лучшее решение для новой платформы?