动态创建各种模型的隐藏表单字段(MVC 4)

时间:2015-03-25 02:31:29

标签: javascript c# jquery asp.net-mvc

我正在尝试为一组属性动态创建隐藏字段,但是当我提交表单时,我收到500服务器错误。我确认了以下内容:

  • 我在foreach语句中迭代的属性是正确的。
  • property.Name是NewItem.GetType()
  • 检索的类型的有效属性名称

这就是我所拥有的:

查看

@model PaneViewModel

using (Ajax.BeginForm("AddItem", "Action", new AjaxOptions
{
    UpdateTargetId = "tool-wrapper",
    HttpMethod = "POST",
}))
{
    // Some standard input fields here (these are working properly).

    [...]

    // Here's what's broken:
    @foreach (var property in Model.NewItem.GetType().GetProperties().Where(<criteria here>))
    {
        @Html.HiddenFor(m => m.NewItem.GetType().GetProperty(property.Name), column.GetValue(Model.NewItem, null))
    }

    <button type="submit">Add</button>
}

ItemViewModel

public class ItemViewModel
{
    public int SomeField { get; set; }
    public int AnotherField { get; set; }
}

PaneViewModel

public class PaneViewModel
{
    public ItemViewModel NewItem { get; set; }
}

控制器

[HttpPost]
public ActionResult AddItem([Bind(Prefix = "NewItem")] ItemViewModel model)
{
    // Stuff here.
}

值得注意的是,以下内容会在生成的HTML中生成具有正确名称和值的隐藏字段,但隐藏字段的值不会发布到控制器操作:

@foreach (var property in Model.NewItem.GetType().GetProperties().Where(<criteria here>))
{
    @Html.Hidden(property.Name, column.GetValue(Model.NewItem, null))
}

所以似乎问题在于m => m.NewItem.GetType().GetProperty(property.Name)组件

1 个答案:

答案 0 :(得分:1)

  1. 此类逻辑不属于视图
  2. Html.HiddenFor()期望表达式(Expression<Func<TModel, TProperty>>)作为第一个参数,但.GetProperty()会返回 typeof PropertyInfo
  3. 您不应该为属性生成多个隐藏的输入 你的模型,而是使用视图模型来代表什么 你需要编辑(它通过发送额外的数据来降低性能 客户端,然后再次发布回来,没有任何人 可以使用FireBug或类似工具来更改值和您 可能没有更聪明的人。
  4. 但是,如果你想这样做,你可以创建一个html助手,为所有标有[HiddenInput]属性的属性生成隐藏的输入(或者修改这个例子以传递一些条件,过滤所需的属性)

    public static MvcHtmlString HiddenForModel<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
    {
      StringBuilder html = new StringBuilder();
      ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
      var properties = metaData.Properties.Where(p => p.TemplateHint == "HiddenInput");
      foreach(var property in properties)
      {
        html.Append(helper.Hidden(property.PropertyName));
      }
      return MvcHtmlString.Create(html.ToString());
    }
    

    请注意,这也会生成可能不必要的iddata-val-*属性,因此您可以使用

    最小化生成的html
    foreach(var property in properties)
    {
      TagBuilder input = new TagBuilder("input");
      input.MergeAttribute("type", "hidden");
      input.MergeAttribute("name", property.PropertyName);
      input.MergeAttribute("value", string.Format("{0}", property.Model));
      html.Append(input.ToString());
    }