【问题标题】:Is there a way to modify the generated name attribute for TextboxFor, HiddenFor etc through ModelBinder?有没有办法通过ModelBinder修改TextboxFor、HiddenFor等生成的名称属性?
【发布时间】:2015-06-17 11:00:18
【问题描述】:

我研究了这个问题,发现了以下问题:

SO-Link1 SO-Link2

所以这个问题似乎很常见 - 但我真的不喜欢这个解决方案。

问题:

我已经开始挖掘资源,但还没有找到方便的解决方案。现在使用属性是否有内置解决方案?

必须在适当的位置使用动态参数而不是在模型上使用属性非常不方便。

我想我会看看同时通过修改 ModelBinder 可以实现什么 - 我猜一定有某种方法。

更新:

我为什么要这样做?

我想减少网络流量,因为代码中的属性可能很长 + 嵌套。想象一下 200 个复选框 x 40 字节生成的名称。

我已经可以让我的 modelbinder 使用别名 - 但是为了完全自动化它,我需要 TextBoxFor 等方法来使用别名而不是实际的属性名称。

【问题讨论】:

  • 为什么要更改控件的名称属性——这意味着绑定和验证将失败? ModelBinder 的目的是绑定模型(即在提交时),而不是在生成视图时(由 html 助手完成)。你到底想做什么?
  • 您也可以更改模型绑定以通过别名属性工作。原因其实很简单:不必要的网络流量。为什么我要它生成 SomePropertyInSomeClassWhichCouldBeRatherLongForNoGoodReasonWithSomeMoreNesting[0].Value。我宁愿那是“p1[0].Value”
  • 如果您的模型命名约定真的那么糟糕,只需使用视图模型并重命名属性! ModelBinder 与渲染 name 属性无关。这就是 html 助手所做的。
  • @StephenMuecke 不。我不会更改我的属性名称以减少网络流量。我会找到一种方法来做到这一点 - 如有必要,通过为 MVC 做出贡献。我当然不会修改我的 VIEW 来改变我的 MODEL 的传输方式。您应该理解这有意义的原因,而不是告诉我我的命名约定不好。我想优化移动设备的网络流量,而不是降低整个代码库的可读性以满足需求。
  • 我的意思是您应该遵循最佳实践并使用视图模型(请参阅What is ViewModel in MVC?)。您可以随意设置属性名称。

标签: asp.net-mvc model-binding


【解决方案1】:

我个人认为你不应该完全关心 name 属性值的大小。只要您通过 IIS 之类的东西使用压缩,那么您就不会节省那么多。

但是,您可以通过创建自定义 HTML 帮助程序来实现您所追求的目标,该帮助程序将创建您想要的 HTML 标记。

示例模型

public class UserModel
{
    public string FullName { get; set; }
}

助手

public static MvcHtmlString CustomTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string name)
{
    var fieldName = ExpressionHelper.GetExpressionText(expression);

    //
    // Pass in alias or call method to get alias here
    //
    var fullBindingName = String.IsNullOrWhiteSpace(name) ? html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName) : name;
    var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);

    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    var value = metadata.Model;

    var 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());

    var validationAttributes = html.GetUnobtrusiveValidationAttributes(fullBindingName, metadata);
    foreach (var key in validationAttributes.Keys)
    {
        tag.Attributes.Add(key, validationAttributes[key].ToString());
    }

    return new MvcHtmlString(tag.ToString(TagRenderMode.SelfClosing));
}

调用视图中的方法

   @Html.TextBoxFor(x => x.FullName)

   @Html.CustomTextBoxFor(x => x.FullName, "FName")

输出

<input id="FullName" type="text" value="Heymega" name="FullName">
<input id="FName" type="text" value="Heymega" name="FName">

【讨论】:

  • 虽然这种方式肯定会起作用,但我不想包装我们使用的每个组件,只是为了控制生成的名称。这就是为什么我试图使用 MetadataProvider 以某种方式完成这项工作。不过还没有完成。
  • @AndreasMüller 抱歉,这不是您想要的。祝你编码好运!
猜你喜欢
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 2021-03-04
  • 1970-01-01
相关资源
最近更新 更多