Asp.net mvc 使用TextBoxFor设置具有命名空间前缀的HTML属性

Asp.net mvc 使用TextBoxFor设置具有命名空间前缀的HTML属性,asp.net-mvc,attributes,collection-initializer,Asp.net Mvc,Attributes,Collection Initializer,我正在转换一些现有HTML以使用ASP.NET MVC,并且有一些表单包含输入字段,这些字段具有包含名称空间前缀的附加属性(目前我需要保留这些属性): <input type="text" foo:required="true" foo:message="Please enter a username" /> 但是,由于foo:required(etc)中的冒号,此语法无效 相反,我必须使用更详细的字典初始值设定项语法: @Html.TextBoxFor( model =&

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

<input type="text" foo:required="true" foo:message="Please enter a username" />
但是,由于
foo:required
(etc)中的冒号,此语法无效

相反,我必须使用更详细的字典初始值设定项语法:

@Html.TextBoxFor(
    model => model.Username,
    new Dictionary<string, object>
    {
        { "foo:required", "true" },
        { "foo:message", "Please enter a username" }
    })
@Html.TextBoxFor(
model=>model.Username,
新词典
{
{“foo:required”,“true”},
{“foo:message”,“请输入用户名”}
})
是否有可能在第一个语法上使用变体,以某种方式(因为缺少更好的词)转义冒号


在这种情况下,
TextBoxFor
helper方法没有真正的帮助,只保留现有的原始HTML,并将
value=“@Model.UserName”
添加到
input
元素中会更简单吗?

第一种语法是使用匿名对象,关于如何应用的规则相同:

  • 您可以使用类
    Lu、Ll、Lt、Lm、Lo或Nl的任何unicode字符
  • 您可以像在
    new{@class=“foo”}中一样,使用“@”替换C#关键字
由于冒号属于,因此不能在标识符中使用。(在C#中,可以使用static方法检查任何字符的类)

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

回到你的案例中,关于你的选择,如果那些没有被广泛使用(比如在一些视图中),我会考虑使用<代码> TrimBox为帮助器的字典语法。您仍将获得与模型绑定同步的id\name属性的自动生成,并且您将从模型元数据中获得任何其他属性,如不引人注目的验证属性。(虽然查看了要保留的属性,但似乎不需要不引人注目的验证:)

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

如果您在整个应用程序中广泛使用它,那么在我看来,最明智的方法可能是创建您自己的助手,如
@Html.LegacyTextBoxFor(…)
。该帮助器将呈现您想要kepp的那些遗留属性,并且您可以合并类似于用于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:

<input foo:message="Please enter a value." foo:required="true" id="UserName" name="UserName" type="text" value="">

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


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

您不能简单地转义冒号,因为foo:required基本上是一个属性,因此名称需要适合C#property、variable、function和type名称所允许的字符。
@Html.LegacyTextboxFor(model => model.UserName, new FooAttributes {Required=true, Message="Please enter a value." })
<input foo:message="Please enter a value." foo:required="true" id="UserName" name="UserName" type="text" value="">