【问题标题】:ASP.NET MVC Add Child Records DynamicallyASP.NET MVC 动态添加子记录
【发布时间】:2013-10-23 23:04:43
【问题描述】:

使用实体数据框架,我定义了一个名为 Client 的模型,它只包含一个 id 和一个名称。然后,我与另一个名为 Appointment 的模型建立了关联,其中包含一个 id 和一个日期。

对于表单,我希望允许用户创建一个新客户端并在同一个表单上添加约会(在创建客户端之前)。我有部分工作(添加一个约会)。

在控制器中:

[HttpPost]
public ActionResult Create(Client client)
{
    var appointment = new Appointment();
    UpdateModel(appointment);
    client.Appointments.Add(appointment);
    db.AddToClients(client);
    db.SaveChanges();
    return RedirectToAction("Index");
}

在视图中:

<div class="editor-label">
    <%= Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
    <%= Html.TextBoxFor(model => model.Name) %>
    <%= Html.ValidationMessageFor(model => model.Name) %>
</div>
<% Html.RenderPartial("Appointment", new Appointment()); %>

“部分”观点:

<div class="editor-label">
    <%= Html.LabelFor(model => model.AppointmentDate) %>
</div>
<div class="editor-field">
    <%= Html.TextBoxFor(model => model.AppointmentDate) %>
    <%= Html.ValidationMessageFor(model => model.AppointmentDate) %>
</div>

但是,由于以下几个原因,这并不理想:

  1. 只能添加一个约会
  2. 如果存在任何名称冲突(例如,ClientAppointment 表中名为 Comments 的字段),则会出现问题,因为没有对字段名称进行前缀,这也可以防止多个约会被也添加了

我可以做些什么来允许添加多个约会,即当单击“新约会”以允许尽可能多的约会时,使用按钮在页面上呈现部分视图(可能使用 AJAX)?我还希望这是一个共享视图,可用于创建和编辑记录以及以相同的形式添加/删除约会。

更新
使用 ViewModel 取得了一些进展:

public class ClientViewModel
{
    public Client Client { get; set; }
    public List<Appointment> Appointments { get; set; }
}

控制器:

public ActionResult Create()
{
    Client c = new Client();
    List<Appointment> appointments = new List<Appointment>();
    appointments.Add(new Appointment() { AppointmentDate = DateTime.Now });
    appointments.Add(new Appointment() { AppointmentDate = DateTime.Now.AddMonths(1) });

    var model = new ClientViewModel
    {
        Client = c,
        Appointments = appointments
    };
    return View(model);
}

[HttpPost]
public ActionResult Create(ClientViewModel m)
{
    try
    {
        foreach (var appointment in m.Appointments)
        {
            m.Client.Appointments.Add(appointment);
        }
        db.AddToClients(m.Client);

        db.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

查看(对于约会,不适用于foreach 循环,因为每个约会都以Appointment_ 而不是Appointment[0]_ 为前缀):

<%= Html.EditorFor(model => Model.Client) %>
<% for (int i = 0; i < Model.Appointments.Count(); i++) { %>
    <%= Html.EditorFor(model => Model.Appointments[i])%>
<% } %>

这对于为新客户创建约会很好,但是如何编辑它们以及添加新约会而不发回表单?添加时,在现有约会表单下显示一个新约会表单的链接,以及另一个要删除的链接(从视图中隐藏并设置隐藏字段值)。

更新 2
得到它的工作,在第一次创建客户时添加约会。但是,我不确定如何更新现有约会(而不是全部删除并重新添加)。

在控制器中:

[HttpPost]
public PartialViewResult AddAppointment(Appointment appointment, int index)
{
    List<Appointment> appointments = new List<Appointment>();
    for (int i = 0; i < index; i++)
    {
        appointments.Add(null);
    }
    appointments.Add(new Appointment() { AppointmentDate = DateTime.Now });
    ViewData["index"] = index;
    var model = new ClientViewModel
    {
        Appointments = appointments
    };
    return PartialView("Appointment", model);
}

查看:

<%= Html.EditorFor(model => Model.Client) %>
<div id="appointments">
<% for (int i = 0; i < Model.Appointments.Count(); i++) { %>
    <%= Html.EditorFor(model => Model.Appointments[i]) %>
<% } %>
</div>
<a href="javascript:;" id="addappointment">Add Appointment</a>
<script type="text/javascript">
    var appIndex = <%= Model.Appointments.Count() %>;
    $("#addappointment").click(function () {
        $.post(
            "/Client/AddAppointment",
            {"index" : appIndex}, 
            function (result) {
                $("#appointments").append(result);
                // increase index by 1
                appIndex++;
            }
        );
});

【问题讨论】:

    标签: asp.net-mvc entity-framework


    【解决方案1】:

    只是漂浮一些想法..

    如果你让 Appointment 部分视图包含一个表单怎么样。

    使用jQuery/AJAX处理表单的提交:

    $.post(
       "/SomeController/AddAppointment",
            appointment, // grab this from the form
            function (result) { 
               $("#target").html(result); // this will be the div which contains the partial
            }
         );
    

    这会将强类型的 Appointment 发送到以下 Action 方法:

    [HttpPost]
    public PartialViewResult AddAppointment(Appointment appointment)
    {
       // code to persist entity
       // code to add errors to model (if necessary)
       return PartialView("Appointment");
    }
    

    基本上,您使用 AJAX 提交表单,然后将结果重新渲染回部分。结果类似于 AJAX UpdatePanel(以 WebForms 闻名)。

    所以你需要填写详细信息,点击“提交”,详细信息会被发布到控制器(使用 AJAX),然后表单将再次为空白,因此你可以继续添加约会。

    这行得通吗?

    【讨论】:

    • 唯一的问题是“客户端”可能尚未创建。如果我可以在字段名称前加上“约会”并将其放入数组中(即,将 [] 附加到名称中),那么这不起作用(使用 UpdateModel(“约会”,约会)?虽然不知道如何设置它向上
    【解决方案2】:

    有几篇博文解释了模型绑定如何与复杂项目列表一起工作。 您的视图模型方法应该有效,当您想要添加新约会时,只需使用一些 JS 代码在客户端的约会列表(视图模型)中添加一个新项目。

    浏览这些链接,这些链接解释了如果您正确呈现 html,开箱即用的 MVC 模型绑定将如何工作

    http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

    http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      相关资源
      最近更新 更多