ASP.NET MVC:保持用户编辑实体的位置

时间:2009-10-23 15:59:52

标签: asp.net-mvc domain-driven-design

这是一个简单的问题:用户希望以类似网格的方式编辑产品:选择并单击添加,选择并单击添加...然后他们会看到更新的产品列表...然后单击“完成”并保存订单

但是,每个“添加”都有转到服务器,因为它涉及服务器端验证。此外,验证是在域实体内部(例如,订单) - 也就是说,为了进行验证,我需要调用order.Add(product)然后命令决定它是否可以添加产品。

问题是,如果我按订单添加产品,它会保留更改,所以即使用户没有点击“完成”,更改仍然会在那里!

好的,我可能不应该修改订单,直到用户点击完成。但是,如何验证产品呢?这应该由订单实体完成 - 如果产品已经添加,产品不与其他产品冲突等。

另一个问题是,我必须根据订单添加产品并根据其新状态“重建视图/ HTML”(因为它可以大大改变)。但是如果我不坚持订单更改,则下一次添加将从每次相同的订单开始,而不是从更新的订单开始。也就是说,我需要以某种方式跟踪订单的变化。

我看到了几个解决方案:

  1. 每次用户单击“添加”,从数据库检索订单,并添加所有新产品(从页面中),但不保留它,只需返回“查看”(订单)。问题是我无法从POST / Edit重定向到GET / Edit - 因为所有数据只存在于POST数据中,而GET会丢失它。这意味着刷新页面不能很好地工作(F5,你得到重复的请求,更不用说浏览器的对话框))。
    • 嗯,我以为可以使用TempData(和MvcContrib帮助程序)重定向到GET。因此在POST到/ Edit之后我处理业务逻辑,获取视图的新数据,并从MvcContrib执行RedirectToAction<>(数据),通过TempData传递数据。但由于TempDate是...... temp ...在F5之后所有数据都丢失了。不行。该死的数据应该以某种方式存储在某处。
  2. 使用POST数据(订单,新产品信息)在Session中存储“编辑对象”。这也可以是数据库。种类“当前项目 - 每页类型”。因此,页面将获得订单ID以及此存储中当前添加的产品。但是从多个页面进行编辑是有问题的。而且我不喜欢在Session中存储临时/当前对象。
  3. 将产品标记为“已确认” - 如果我们进行/订购/展示,我们首先清理订单中所有未经确认的产品。丑陋而混乱的逻辑。
  4. 复制订单 - 临时订单 - 并使/编辑工作。确认会将更改从临时命令移动到持久性。很多丑陋的工作。
  5. 也许是一些AJAX魔术?即“添加”按钮不会重新加载页面,但只会向服务器发送新的+已添加的产品,服务器将验证为订单。添加(产品+新产品)但不会保持更改,只会返回更新订购信息以重建网格。但刷新/ F5将终止所有用户输入的信息。
  6. 还有什么?
  7. 这个问题很常见吗?你是如何解决类似问题的?什么是最佳实践?

2 个答案:

答案 0 :(得分:0)

这在很大程度上取决于您如何实现对象/验证,但您的选项5可能是最好的选择。如果AJAX不是你的事,你可以通过将已经添加但未保存的条目的相关数据写入隐藏字段来完成同样的事情。

换句话说,流程结束了这样的事情:

  1. 用户输入项目。

  2. 将项目发送到服务器并进行验证。返回视图,其中用户在隐藏字段中输入数据。

  3. 用户输入第二项。

  4. 将项目发送到服务器,并验证这两个项目。将返回视图,其中包含隐藏字段中两个项目的数据。

  5. 等。

  6. 到目前为止F5 / Refresh杀死输入的数据...根据我的经验,这不是太大的问题。一个更紧迫的问题是后退/前进按钮,需要使用像Really Simple History这样的东西进行管理。

    如果您想在刷新后继续使页面继续工作,则需要执行以下操作之一:

    1. 将记录保存到数据库,并以某种方式与当前用户关联。
    2. 将记录保留到会话中。
    3. 将记录保留在查询字符串中。
    4. 这些是唯一可用的重定向和刷新存储位置。

答案 1 :(得分:0)

如果我是你,我会想出类似于选项5的东西。既然你说你对Ajax感到满意,你可以试试这个。但在此之前,您将验证逻辑移到Order.Add()方法之外。也许你可以将它移动到另一个名为Validate()的公共函数,它返回一个bool。您仍然可以在Add()方法中调用相同的Validate(),从而在添加订单之前进行必要的验证。

  1. 尝试在客户端进行验证。如果您使用的是jQuery,则可以使用jquery validate插件。但是,如果由于某种原因(例如,当您需要针对数据库验证内容时)这是不可能的。您应该在服务器端进行验证,并返回一个带有'success'布尔标志和可选消息的JSON对象,这只是一种标记数据有效的方法。只有在先前的订单有效时,您才允许用户添加新产品。
  2. 当用户点击完成后,将产品发送到服务器并再次进行验证,但在此往返中保留订单。
  3. 现在,如果我对此有完整的发言权,那么无论何时添加/编辑产品,我都不会进行验证。我会在客户完成任务时进行验证。那将是最简单的解决方案。但是,也许我错过了一些东西。