在MVC中创建“创建”动态地​​将ICollection项添加到模型

时间:2017-07-08 12:26:44

标签: c# asp.net asp.net-mvc razor

找到一个解决方案,但是一个非常难看的解决方案,从底部看,有人可以改进解决方案吗?

所以我有一个像这样的虚拟模型

public class TestModel
{
    public int TestModelID { get; set; }
    public string Name { get; set; }
}

另一个像这样的人

public class Collector
{
    public int CollectorID { get; set; }
    public string CollectorString { get; set; }
    public ICollection<TestModel> MyList { get; set; }
}

我想(以简单的CRUD风格)创建一个新对象 Collector 并填充(稍后动态添加新字段,现在只有一个)ICollection。 这是我的观点

@model TestApplication.Models.Collector

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Collector</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.CollectorString, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CollectorString, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CollectorString, "", new { @class = "text-danger" })
            </div>
        </div>


        <div class="form-group">
            @Html.LabelFor(model => Model.MyList.ToList()[0].Name)
            <div class="col-md-10">
                @Html.EditorFor(model => model.MyList.ToList()[0].Name, new { htmlAttributes = new { @class = "form-control" } })


            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

和控制器

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Collector collector)
{
    if (ModelState.IsValid)
    {
        db.Collectors.Add(collector);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(collector);
}

这是生成的HTML代码(我希望只是相关部分)

<div class="form-group">
    <label for="">Name</label>
    <div class="col-md-10">
        <input class="form-control text-box single-line" name="[0].Name" type="text" value="" />
    </div>
</div>

但是,创建时控制器中的MyList始终为空,为什么? (是的,我知道Haackeds博客条目,仍然无法弄清楚为什么它不起作用)

所以问题是,这一行

@Html.EditorFor(model => model.MyList.ToList()[0].Name, new { htmlAttributes = new { @class = "form-control" } })

虽然非常推荐在MVC中使用,但在此处生成

<input class="form-control text-box single-line" name="[0].Name" type="text" value="" />

显然不起作用。如何让剃须刀将[0].Name更改为MyList[0].Name

**更新:** 所以我找到了一个解决方案,如果这里的硬代码

<input class="form-control text-box single-line" name="MyList[0].Name" type="text" value="" />

控制器理解它,我没有得到null。如何用剃刀解决它?

3 个答案:

答案 0 :(得分:2)

ICollection<T>没有索引器。 IList<T>确实

public class Collector {
    public Collector() {
        MyList = new List<TestModel>(); 
    }
    public int CollectorID { get; set; }
    public string CollectorString { get; set; }
    public IList<TestModel> MyList { get; set; }
}

这将允许

@Html.EditorFor(model => model.MyList[0].Name, new { htmlAttributes = new { @class = "form-control" } })

在视图中生成所需的标记

<input class="form-control text-box single-line" name="MyList[0].Name" type="text" value="" />

也可以在多个项目的循环中使用

<div class="form-group">
@for(int i = 0; i < Model.MyList.Count; i++) {
    @Html.LabelFor(model => Model.MyList[i].Name, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.MyList.ToList()[i].Name, new { htmlAttributes = new { @class = "form-control" } })
    </div>
}
</div>

从控制器初始调用返回模型时,只需确保对模型的集合索引的调用有一个项目。

[HttpGet]
public ActionResult Create() {
    var model = new Collector();
    model.MyList.Add(new TestModel());
    return View(model);
}

答案 1 :(得分:0)

尝试更改收集器类以包含初始化。

   public class Collector
   {
     public Collector() 
     {
        set MyList = new Collection<TestModel>();
     }
    public int CollectorID { get; set; }
    public string CollectorString { get; set; }
    public ICollection<TestModel> MyList { get; set; }
   }

答案 2 :(得分:0)

你可以使用剃刀语法

来做到这一点
<div class="form-group">
  @for(int i = 0; i < Model.MyList.Count; i++) {
      @Html.LabelFor(model => Model.MyList[i].Name, htmlAttributes: new {      @class = "control-label col-md-2" })
      <div class="col-md-10">
         @Html.EditorFor(model => model.MyList[i].Name, new { htmlAttributes = new { @class = "form-control" } })
      </div>
  }
</div>