ASP.NET MVC动态添加子记录

时间:2010-10-29 11:48:02

标签: asp.net-mvc entity-framework

使用实体数据框架,我有一个名为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. 如果存在任何名称冲突(例如CommentsClient表中都称为Appointment的字段),则会出现问题,因为字段名称上没有前缀,防止添加多个约会
  3. 如果单击“新约会”以允许尽可能多的约会,我可以做什么来允许添加多个约会,即使用按钮呈现页面上的部分视图(可能使用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++;
                }
            );
    });
    

2 个答案:

答案 0 :(得分:2)

只是浮出一些想法..

如果您将约会部分视图包含表单,该怎么办?

使用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
        }
     );

哪会将强类型的约会发送到以下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),然后表单会再次出现空白,这样你就可以继续添加约会。

那会有用吗?

答案 1 :(得分:0)

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

通过这些链接解释如果正确渲染html,开箱即用的MVC模型绑定将如何工作

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

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