繁体   English   中英

在MVC视图中未正确删除模型子对象

[英]Model Child object is not correctly removed in MVC view

我有一个基于主细节模型的MVC主细节视图和每个细节记录的删除按钮。

按下删除按钮后,我将发布要删除的ID和整个模型,然后从模型中删除正确的详细记录并将其返回到视图。

问题在于该视图呈现了不正确的详细记录。 无论按什么键,它实际上都会删除最后一条记录。

型号

public class Customer
{
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public string Description { get; set; }

    public List<Contact> CustomerContacts { get; set; }
}
public class Contact
{
    public int ID { get; set; }
    public int CustomerID { get; set; }
    public string ContactName { get; set; }
    [Required]
    public string ContactEmail { get; set; }
}

控制器动作

    public ActionResult Index()
    {
        Customer customer = new Customer(){ ID=1, Name="CustOne", Description="Descr1"};

        Contact contact1 = new Contact() { ID = 1, CustomerID = 1, ContactName = "Cont_One", ContactEmail = "a@b.com" };
        Contact contact2 = new Contact() { ID = 2, CustomerID = 1, ContactName = "Cont_Two", ContactEmail = "b@c.com" };
        customer.CustomerContacts = new List<Contact>();
        customer.CustomerContacts.Add(contact1);
        customer.CustomerContacts.Add(contact2);

        return View(customer);
    }

    [HttpPost]
    public ActionResult Index(string btnSubmit, Customer customer)
    {
        int CustomerContactID = Convert.ToInt32(btnSubmit);

        if (!ModelState.IsValid)
        {
            return View(customer);
        }

        int indexOfCust = customer.CustomerContacts.FindIndex(c => c.ID == CustomerContactID);
        customer.CustomerContacts.RemoveAt(indexOfCust);

        return View(customer);
    }

风景:

    @model MyMVCProblem.Models.Customer
@{
    ViewBag.Title = "Home Page";
}

<br />
@using (Html.BeginForm())
{
    <table>
        <tr>
            <td>Name</td>
            <td>
                @Html.TextBoxFor(m => m.Name)
                @Html.ValidationMessageFor(m => m.Name)
            </td>
        </tr>
        <tr>
            <td>Description</td>
            <td>
                @Html.TextAreaFor(m => m.Description)
            </td>
        </tr>
    </table>


    for (int i = 0; i < Model.CustomerContacts.Count; i++)
    {
        <table>
            <tr>
                <td>Contact Name</td>
                <td>
                    @Html.HiddenFor(m => m.CustomerContacts[i].ID)
                    @Html.TextBoxFor(m => m.CustomerContacts[i].ContactName)
                    @Html.ValidationMessageFor(m => m.CustomerContacts[i].ContactName)
                </td>
            </tr>
            <tr>
                <td>Contact e-mail</td>
                <td>
                    @Html.TextBoxFor(m => m.CustomerContacts[i].ContactEmail)
                    @Html.ValidationMessageFor(m => m.CustomerContacts[i].ContactEmail)
                </td>
            </tr>
        </table>
        <button type="submit" name="btnSubmit" id="Submit" value="@Model.CustomerContacts[i].ID">Delete</button>
        <br /><br />
    }
}

一种可能的解决方案是清除ModelState。
下面是示例:

[HttpPost]
    public ActionResult Index(string btnSubmit, Customer customer)
    {
        int CustomerContactID = Convert.ToInt32(btnSubmit);

        if (!ModelState.IsValid)
        {
            return View(customer);
        }

        int indexOfCust = customer.CustomerContacts.FindIndex(c => c.ID == CustomerContactID);
        customer.CustomerContacts.RemoveAt(indexOfCust);
        ModelState.Clear();
        return View(customer);
    }

我建议的一种方法是,使用局部视图和$ .ajax调用delete函数,但不确定是否能真正解决您的问题。 换句话说,您可以在使用List模型的局部视图中呈现CustomerContacts表。 这样,您可以在页面首次加载时使用

<div id="customerContactsList">
    @{ Html.RenderPartial("_CustomerContactsList", Model.CustomerContacts); } 
</div>

然后,您可以使用循环来呈现该部分内的表。 一旦实现了这一点,就可以在控制器中使用POST方法,例如

[HttpPost]
public ActionResult DeleteCustomerContact(int id)
{
  // Call the delete function 
  // e.g. DeleteContact(id);
  // Then re-read your contacts list
  List<CustomerContacts> contacts = GetContacts(...);

  return PartialView("_CustomerContactsList", contacts);
}

在您的表单代码上,为delete按钮添加一个回调以调用所述方法,并在成功时仅呈现带有列表的部分视图。 只需添加一个ajax调用并将其绑定到click事件

$('btnDelete').click(function() {
        $.ajax({
            url: 'DeleteCustomerContact',
            type: 'POST',
            data: customerContactId,
            dataType: 'text',
            contentType: 'application/json; charset=utf-8',
            success: function ( result ) {
                  $('#customerContactsList').html(result);
            },
            error: function () {
                alert('error');
            }
        });
});

现在,由于我不确定实际原因是什么,因此不能保证解决您的问题,但这是一种非常清晰的方法,因为一旦调用delete方法,客户联系人列表始终会刷新。

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM