使用TextBoxFor设置具有名称空间前缀的HTML属性

Ric*_*ett 7 asp.net-mvc attributes collection-initializer

我正在转换一些现有的HTML以使用ASP.NET MVC,并且有一些包含输入字段的表单,这些字段具有包含命名空间前缀的附加属性(现在,我需要保留):

<input type="text" foo:required="true" foo:message="Please enter a username" />
Run Code Online (Sandbox Code Playgroud)

我想使用TextBoxForhelper方法重载,允许htmlAttributes使用collection initializer语法指定:

@Html.TextBoxFor(
    model => model.Username,
    new { foo:required="true", foo:message="Please enter a username" })
Run Code Online (Sandbox Code Playgroud)

但是,由于foo:required(etc)中的冒号,此语法无效.

相反,我不得不使用这个更详细的字典初始化语法:

@Html.TextBoxFor(
    model => model.Username,
    new Dictionary<string, object>
    {
        { "foo:required", "true" },
        { "foo:message", "Please enter a username" }
    })
Run Code Online (Sandbox Code Playgroud)

是否可以使用第一种语法的变体,以某种方式逃避(因为缺少一个更好的词)冒号?

要么

这是TextBoxFor辅助方法实际上没有帮助的情况,只是保留现有的原始HTML并添加value="@Model.UserName"input元素会更简单吗?

Dan*_*.G. 3

第一种语法是使用匿名对象,关于如何在 C# 中创建标识符的相同规则 适用于该匿名对象:

\n\n
    \n
  • 您可以使用类的任何 unicode 字符Lu, Ll, Lt, Lm, Lo, or Nl
  • \n
  • 您可以使用“@”对 C# 关键字进行转义,如下所示new { @class = "foo" };
  • \n
\n\n

由于冒号属于Po unicode 类,因此不能在标识符中使用。(在 C# 中,您可以使用静态方法char.GetUnicodeCategory来检查任何字符的类别)

\n\n

此外,仅在 MVC 中,当在帮助程序中使用匿名对象作为 html 属性时,任何带下划线的属性名称都将替换为连字符。这是由于方法HtmlHelper.AnonymousObjectToHtmlAttributes

\n\n

回到您的案例并考虑您的选择,如果这些选项使用得不太广泛(例如在几个视图中),我会考虑保留助手的字典语法TextBoxFor。您仍然可以自动生成与模型绑定同步的 id\\name 属性,并且可以从模型元数据中获取任何其他属性,例如不显眼的验证属性。(虽然查看您想要保留的属性,但似乎您\xc2\xb4t不需要不引人注目的验证属性:))

\n\n

但是,如果 id\\name 就像属性名称一样简单,并且您不需要使用帮助程序自动生成的任何其他 html 属性,那么使用原始 HTML 是有意义的。(因为字典语法相当难看)

\n\n

如果您在应用程序中广泛使用它,那么在我看来,最明智的方法可能是创建您自己的助手,例如@Html.LegacyTextBoxFor(...). 该帮助器将呈现您想要保留的那些旧属性,并且您可以合并类似于用于 id\\name 属性创建的标准帮助器的附加逻辑。

\n\n

像这样的东西:

\n\n
public class FooAttributes\n{\n    public bool Required { get; set; }\n    public string Message { get; set; }\n}\n\npublic static class FooHelper\n{\n    public static MvcHtmlString LegacyTextboxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, FooAttributes fooAttributes)\n    {\n        var fieldName = ExpressionHelper.GetExpressionText(expression);\n        var fullBindingName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);\n        var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);\n\n        var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);\n        var value = metadata.Model;\n\n        TagBuilder tag = new TagBuilder("input");\n        tag.Attributes.Add("name", fullBindingName);\n        tag.Attributes.Add("id", fieldId);\n        tag.Attributes.Add("type", "text");\n        tag.Attributes.Add("value", value == null ? "" : value.ToString());\n\n        if (fooAttributes != null)\n        {\n            if (fooAttributes.Required) tag.Attributes.Add("foo:required", "true");\n            if (!String.IsNullOrEmpty(fooAttributes.Message)) tag.Attributes.Add("foo:message", fooAttributes.Message);\n        }\n\n        return new MvcHtmlString(tag.ToString(TagRenderMode.SelfClosing));\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

可以用作:

\n\n
@Html.LegacyTextboxFor(model => model.UserName, new FooAttributes {Required=true, Message="Please enter a value." })\n
Run Code Online (Sandbox Code Playgroud)\n\n

并会生成这个html:

\n\n
<input foo:message="Please enter a value." foo:required="true" id="UserName" name="UserName" type="text" value="">\n
Run Code Online (Sandbox Code Playgroud)\n\n

一旦您有了自己的助手,您就可以添加额外的逻辑,例如将从模型元数据及其数据注释属性生成这些属性的逻辑......

\n\n

我的回答超出了预期,但我希望它能有所帮助!

\n