Использование 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, например логику, которая будет генерировать эти атрибуты из метаданных модели и ее атрибутов аннотаций данных...

я расширил свой ответ больше, чем намеревался, но я надеюсь, что это поможет!