【问题标题】:MVC editing complex object stored in hidden fieldsMVC 编辑存储在隐藏字段中的复杂对象
【发布时间】:2014-01-20 00:42:15
【问题描述】:

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

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

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

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

【问题讨论】:

  • 这个问题不是很简单...作为读者,我不确定您是如何从第一段开始将所有内容存储在隐藏字段中的。你所说的只是你想为一个可以包含多层列表的复杂对象创建一个编辑表单。这绝不意味着所有内容都应该存储在隐藏字段中。我现在才稍微了解你在最后一段之后的问题。
  • 我不明白为什么您不能在服务器端使用所有常规输入呈现普通表单,然后根据需要切换输入的可见性,然后针对您显示的场景文本,但您不希望他们能够编辑它,只需将其设为只读即可。然后,如果您不喜欢默认设置,您可以将自己的样式应用于只读输入。
  • 我在 asp.net mvc 框架和 AngularJS 中都做到了这一点。 Angular 是一个救星。使用 Angular,所有这些活动都很容易。

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


【解决方案1】:

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

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

基本上,我认为您将此事复杂化了一点。如果您在这里应用一些关注点分离,您会发现一切都变得多么容易,实际上它非常容易实现,最重要的是更容易维护和扩展。

从模型开始,我们假设你有一个名为Company 的全能模型,具有以下属性:

  • 公司 ID(整数)
  • 公司名称(字符串)
  • CompanyLegalID(字符串)
  • 公司注册号(字符串)
  • ContactInfo(ContactInfo 类)
  • HeadQuaterAddress('Address` 类)
  • 分支(Branch 类列表)
  • 员工(Employee 类列表)

并且属性列表可以永远持续下去。将这个模型分解成更小的模型会更容易,超级容易。制作具有以下属性的CompanyModel 模型...

  • 公司 ID(整数)
  • 公司名称(字符串)
  • CompanyLegalID(字符串)
  • 公司注册号(字符串)

然后制作一个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>

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

希望这一切对你有意义

【讨论】:

    【解决方案2】:

    Jeditable http://www.appelsiini.net/projects/jeditable 做同样的事情并且更容易实现

    【讨论】:

      【解决方案3】:

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

      正如我在问题中所说,客户端-服务器往返由 MVC 处理,具有(大部分)隐藏字段。以后可以通过在 JSON 中编码一些东西而不是隐藏字段来进行优化,它不会影响系统的其余部分。

      普通字段存储在普通编辑器中,而不是隐藏字段。从客户端-服务器往返的角度来看,这没有什么区别。所以这些可以就地编辑。

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

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

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

      我们需要将 Person 编辑器模板绑定到存储在隐藏字段中的 Person 对象。根据用户单击的行,我们得到一个索引,并将Model.Persons[index] 绑定到该模板。 Knockout.js 是 JS 绑定的理想选择。它会来回复制所有字段。

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

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

      【讨论】:

        猜你喜欢
        • 2015-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-17
        • 1970-01-01
        • 2012-11-03
        • 1970-01-01
        相关资源
        最近更新 更多