Использование TextBoxFor для установки атрибутов HTML, имеющих префикс пространства имен
Я конвертирую некоторый существующий HTML для работы с ASP.NET MVC, и у меня есть некоторые формы, содержащие поля ввода, которые имеют дополнительные атрибуты (которые на данный момент мне нужно сохранить), которые содержат префикс пространства имен:
<input type="text" foo:required="true" foo:message="Please enter a username" />
Я хотел бы использовать TextBoxFor
перегрузка вспомогательного метода, которая позволяет htmlAttributes
указывается с использованием синтаксиса инициализатора коллекции:
@Html.TextBoxFor(
model => model.Username,
new { foo:required="true", foo:message="Please enter a username" })
Однако этот синтаксис недопустим из-за двоеточия в foo:required
(так далее).
Вместо этого мне нужно использовать этот более подробный синтаксис инициализатора словаря:
@Html.TextBoxFor(
model => model.Username,
new Dictionary<string, object>
{
{ "foo:required", "true" },
{ "foo:message", "Please enter a username" }
})
Можно ли использовать вариант первого синтаксиса, каким-то образом избегая (из-за отсутствия лучшего слова) двоеточия?
Или же
Это сценарий, где TextBoxFor
вспомогательный метод не очень помогает, и было бы проще просто сохранить существующий необработанный HTML и добавить value="@Model.UserName"
к input
элемент?
1 ответ
Первый синтаксис использует анонимный объект, для которого применяются те же правила относительно того, как создавать идентификаторы в C#:
- Вы можете использовать любой юникодный символ классов
Lu, Ll, Lt, Lm, Lo, or Nl
- Вы можете использовать ключевые слова C#, используя "@", как в
new { @class = "foo" };
Так как двоеточие принадлежит классу Unicode Po, его нельзя использовать в идентификаторе. (В C# вы можете использовать статический метод char.GetUnicodeCategory для проверки класса любого символа)
Кроме того, и только в MVC при использовании анонимного объекта для атрибутов html в помощнике любое имя атрибута с подчеркиванием будет заменено дефисами. Это связано с методом HtmlHelper.AnonymousObjectToHtmlAttributes
Возвращаясь к вашему случаю и касаемо ваших вариантов, если они не слишком широко используются (например, в нескольких видах), я бы остановился на синтаксисе Dictionary TextBoxFor
помощник. Вы по-прежнему будете автоматически генерировать свойства id \ name в синхронизации с привязкой модели, а также будете получать любые другие атрибуты из метаданных модели, такие как ненавязчивые атрибуты проверки. (хотя, глядя на атрибуты, которые вы хотите сохранить, кажется, вам не понадобятся ненавязчивые проверочные атрибуты:))
Однако, если идентификатор \ имя будет таким же простым, как и имя свойства, и вам не понадобятся никакие другие атрибуты html, которые будут сгенерированы автоматически с помощью помощника, тогда переход к необработанному HTML имеет смысл. (так как синтаксис словаря довольно некрасивый)
Если вы широко используете его в приложении, то, на мой взгляд, наиболее разумным подходом может быть создание собственного помощника, например @Html.LegacyTextBoxFor(...)
, Этот помощник отобразит те устаревшие атрибуты, которые вы хотите сохранить, и вы можете добавить дополнительную логику, аналогичную стандартным помощникам для создания атрибута id \ name.
Что-то вроде этого:
public class FooAttributes
{
public bool Required { get; set; }
public string Message { get; set; }
}
public static class FooHelper
{
public static MvcHtmlString LegacyTextboxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, FooAttributes fooAttributes)
{
var fieldName = ExpressionHelper.GetExpressionText(expression);
var fullBindingName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var value = metadata.Model;
TagBuilder tag = new TagBuilder("input");
tag.Attributes.Add("name", fullBindingName);
tag.Attributes.Add("id", fieldId);
tag.Attributes.Add("type", "text");
tag.Attributes.Add("value", value == null ? "" : value.ToString());
if (fooAttributes != null)
{
if (fooAttributes.Required) tag.Attributes.Add("foo:required", "true");
if (!String.IsNullOrEmpty(fooAttributes.Message)) tag.Attributes.Add("foo:message", fooAttributes.Message);
}
return new MvcHtmlString(tag.ToString(TagRenderMode.SelfClosing));
}
}
Это можно использовать как:
@Html.LegacyTextboxFor(model => model.UserName, new FooAttributes {Required=true, Message="Please enter a value." })
И сгенерирует этот HTML:
<input foo:message="Please enter a value." foo:required="true" id="UserName" name="UserName" type="text" value="">
И когда у вас есть свой помощник, вы можете добавить дополнительную логику, например логику, которая будет генерировать эти атрибуты из метаданных модели и ее атрибутов аннотации данных...
Я расширил свой ответ больше, чем предполагалось, но я надеюсь, что это поможет!