MVC编辑存储在隐藏字段中的复杂对象

时间:2014-01-02 14:28:15

标签: c# javascript asp.net-mvc datagrid model-binding

假设我有一个包含列表的非常庞大的模型,甚至那些列表也可以包含包含其他列表的对象。我想在没有AJAX的MVC4(或5)中为它创建一个编辑表单。

所以我认为第一部分是将整个对象存储在隐藏字段的客户端。列表绑定就像魅力一样,请参阅http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/。现在完整的往返工作正在进行中,我可以将整个对象推送到绑定隐藏字段中的客户端,它会在提交时返回给我,并将发布的隐藏字段放入复杂对象,嵌套列表和所有内容中。

列表或其他对象应根据某些操作进行编辑。一种情况是单个对象或列表项显示为不可编辑,当用户单击它时,它就地可编辑,因此例如网格中的单元格成为文本框。另一种情况是单个对象或列表项根本不显示,当用户单击按钮时,会出现一个带有文本输入字段的弹出窗口。

是否有图书馆或经过验证的方法可以做到这一点?

3 个答案:

答案 0 :(得分:4)

  

是否有图书馆或经过验证的方法可以做到这一点?

究竟是为了什么?在视图中显示大型模型进行编辑?使网格可编辑?或者弹出网格记录进行编辑?

基本上,我认为你有点过于复杂。如果你在这里应用一些关注点,你就会发现一切都变得容易,事实上它非常容易实现,最重要的是更容易维护和扩展。

从模型开始,让我们假设你已经拥有了这个名为Company的强大的大型模型,其中包含以下属性:

  • CompanyID(int)
  • CompanyName(string)
  • CompanyLegalID(string)
  • CompanyRegistrationNumber(string)
  • ContactInfo(ContactInfo class)
  • HeadQuaterAddress('地址`类)
  • 分支(Branch类列表)
  • 员工(Employee班级列表)

属性列表可以永远持续下去。将这个模型分解为更小的模型会更容易,更容易。使用以下属性制作CompanyModel模型...

  • CompanyID(int)
  • CompanyName(string)
  • CompanyLegalID(string)
  • CompanyRegistrationNumber(string)

然后制作CompanyContactInfo模型,依此类推。得到这个想法?同样,关注点的分离简化了很多事情。然后,创建操作方法和视图以读取/编辑这些模型。

现在列出您想要做的大型对象的属性。例如,对于Employee个对象的列表,使用以下属性创建CompanyEmployeesModel模型会更容易:

  • CompanyId(int)
  • 员工(EmployeeModel班级列表)

然后创建一个控制器操作方法来显示员工列表...

public ActionResult EmployeeList(int companyId)
{
    var employees = BusinessLogic.Get_Me_Employees_For(companyId);
    CompanyEmployeesModel model = new CompanyEmployeesModel();
    model.CompanyId = companyId;
    model.Employees = employees;

    return View(model);
}

希望你到目前为止得到这个想法。在视图中只需创建一个css格式的表来显示员工列表,razor使它变得非常简单......

<table class="grid">
   <tr>
      <th></th>
        <th>
            Name
         </th>
         <th>
            Phone
          </th>
    </tr>

            @{
                 var alt = false;

                foreach (var emp in Model.Employees)
                {                    
                    <tr class="@(alt ? "alt" : string.Empty)">
                        <td class="cmd">
                            @ActionLink("edit", "Edit", "Employees", new { empId = emp.Id}, null)
                        </td>
                        <td>@emp.Name</td>
                        <td>@emp.Phone</td>
                    </tr>

                    alt = !alt;
                }

            }
</table>

请注意,表格的第一列有链接“编辑”,可以将用户带到Edit控制器的Employee操作方法,显然您将完成与您一直相同的操作较小的型号。我所做的只是分离逻辑,模型,视图,使它们更简单,更易于维护和更容易理解。

希望这对你有意义

答案 1 :(得分:1)

Jeditable http://www.appelsiini.net/projects/jeditable执行相同的操作并且更容易实现

答案 2 :(得分:0)

非常庞大的模型是业务需求,它必须作为一个实体进行编辑,最好是在一个页面上,它非常有意义,但我不能谈论它。我原本以为(或希望)有一个易于描述的解决方案,但显然,这在MVC中并不常见。它与AJAX非常不同,它有其优点和缺点。当然,它被更广泛地使用,因此有更多的记录。没有AJAX,只有一次往返,有点大,但它是一种更流畅的用户体验。无论如何,这是一个粗略的指导如何按照我的要求去做。

客户端 - 服务器往返由MVC处理(主要是)隐藏字段,如我在问题中所述。稍后可以通过在JSON中编码一些内容而不是隐藏字段来优化它,它不会影响系统的其余部分。

普通字段存储在普通编辑器中,而不是隐藏字段中。从客户端 - 服务器往返的角度来看,它没有任何区别。所以这些可以在适当的位置进行编辑。

网格渲染也很容易。在这种情况下,服务器端MVC网格不是最理想的,因为它们会将冗余数据发送到客户端。幸运的是,有更多的客户端网格解决方案,它们本质上是独立于服务器平台的。只需从隐藏字段中收集所需数据,并使用JavaScript网格库在页面加载时从中构建网格。当然,正如我所说,列表可以包含大量数据和其他嵌套列表,但在这个简单的网格中,必须选择一些必要的列,没有问题。

现在有趣的是,如何使用所有复杂数据编辑网格行。假设我的模型中有一个人员列表,他们有一个地址列表。有一个Person网格,当你点击一行时,你希望最终用户能够编辑一个Person的其他数据以及他的地址。

首先,必须事先将Person编辑器模板发送到客户端。我们需要将该编辑器模板放在我们的视图中,并隐藏它。每当用户想要编辑一个人时,我们都会创建一个包含该编辑器模板内容的JS对话框。

我们需要将Person编辑器模板绑定到存储在隐藏字段中的Person对象。根据用户点击的行,我们得到一个索引,然后将Model.Persons[index]绑定到该模板。 Knockout.js是JS绑定的一个很好的候选者。它可以来回复制所有字段。

MVC编辑器模板还可以包含验证逻辑。在这种情况下没问题,因为我们将编辑器模板作为一个整体呈现给客户端。验证将在弹出窗口内发生,没有任何魔法。当用户按下保存按钮时,将运行验证,当成功时,我们使用绑定引擎将弹出内容复制回隐藏字段。

这不是最简单的事情,但它非常简单。实际上,需要几个不同的JS库,而不是我希望的。因此,如果有人想在没有AJAX的情况下在单个页面上编辑复杂模型,那肯定是可能的。它仍然没有完整记录,因为我无法分享更多细节。但它有它的优点:只有一次往返,因此用户体验更快,并且不需要在服务器上维护状态,所有数据都被检索并在一次往返中保存为一个实体。