Использование 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" };
так как двоеточие принадлежит класс Юникода Po его нельзя использовать в идентификаторе. (В C# вы можете использовать статический метод char.GetUnicodeCategory для того, чтобы проверить класс любого персонажа)
кроме того, и только в MVC, при использовании анонимного объекта для атрибутов html в помощнике любое имя атрибута с подчеркиваниями будет заменено дефисами. Это связано с методом HtmlHelper.AnonymousObjectToHtmlAttributes
вернемся к вашему случаю и относительно ваших вариантов, если они не слишком широко используются (например, в нескольких представлениях), я бы рассмотрел оставаясь с синтаксисом словаря TextBoxFor
помощником. Вы все равно получите автоматическое создание свойств id\name в синхронизации с привязкой модели, и вы получите любые другие атрибуты из метаданных модели, такие как ненавязчивые атрибуты проверки. (хотя, глядя на атрибуты, которые вы хотите сохранить, кажется, вам не понадобятся ненавязчивые проверки:))
однако, если id\name будет таким же простым, как имя свойства, и вам не нужны другие атрибуты html, которые будут генерироваться автоматически с помощью помощника, а затем переход к необработанному HTML имеет смысл. (поскольку синтаксис словаря довольно уродлив)
если вы используете его широко по всему приложению, то, на мой взгляд, наиболее разумным подходом может быть создание собственного помощника, например @Html.LegacyTextBoxFor(...)
. Этот помощник отобразит те устаревшие атрибуты, которые вы хотите kepp, и вы можете включить логику additionaly, подобную стандартным помощникам для атрибута 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="">
и как только у вас есть свой собственный помощник, вы можете добавить логику additionaly, например логику, которая будет генерировать эти атрибуты из метаданных модели и ее атрибутов аннотаций данных...
я расширил свой ответ больше, чем намеревался, но я надеюсь, что это поможет!