【发布时间】:2009-10-23 15:59:52
【问题描述】:
这是一个简单的问题:用户希望以网格方式编辑产品:选择并单击添加,选择并单击添加...他们看到更新的产品列表...然后单击“完成”并保存订单.
但是,每个“添加”必须去服务器,因为它涉及服务器端验证。此外,验证是在域实体内部(比如 Order)——也就是说,要进行验证,我需要调用 order.Add(product),然后 order 决定它是否可以添加产品。
问题是,如果我将产品添加到订单中,它会保留更改,因此即使用户不点击“完成”,更改仍然存在!
好的,我可能不应该在用户单击完成之前修改订单。但是,我该如何验证产品呢?这应该由订单实体完成 - 如果产品已经添加,如果产品与其他产品不冲突,等等。
另一个问题是,我必须将产品添加到订单中并根据其新状态“重建视图/HTML”(因为它可能会发生很大变化)。但是,如果我不坚持订单更改,则下一次添加每次都会从相同的订单开始,而不是从更新的订单开始。也就是说,我需要以某种方式跟踪订单的更改。
我看到了几种解决方案:
- 每次用户单击添加时,从数据库中检索订单,并添加所有新产品(从页面),但不要持久化,只需返回视图(订单)。问题是我无法从 POST /Edit 重定向到 GET /Edit - 因为所有数据只存在于 POST 数据中,而 GET 会丢失它。这意味着刷新页面不能以一种很好的方式工作(F5 并且您收到重复的请求,更不用说浏览器的对话框了))。
- 嗯,我想我可以使用 TempData(和 MvcContrib 帮助程序)重定向到 GET。因此,在 POST 到 /Edit 之后,我处理业务逻辑,获取新数据以供查看,并从通过 TempData 传递数据的 MvcContrib 执行 RedirectToAction(data)。但是由于 TempDate 是... temp... 在 F5 之后所有数据都丢失了。不工作。该死的数据应该以这种或另一种方式存储在某个地方。
- 将“编辑对象”与 POST 数据(订单、新产品信息)一起存储在 Session 中。这也可以是数据库。一种“当前项目 - 每页类型”。因此页面将从该存储中获取订单 ID 和当前添加的产品。但是从多个页面进行编辑是有问题的。而且我不喜欢在 Session 中存储临时/当前对象。
- 将产品标记为“已确认” - 如果我们执行 /order/show,我们首先从订单中清除所有未确认的产品。丑陋而混乱的逻辑。
- 制作一份订单副本 - 一份临时的 - 并让 /Edit 使用它。确认会将更改从临时订单移动到持久化。很多丑陋的工作。
- 也许是一些 AJAX 魔法? IE。 “添加”按钮不会重新加载页面,只会将新的 + 已添加的产品发送到服务器,服务器将作为订单验证。添加(产品 + 新产品)但 不会 保留更改,只会返回更新的订购信息以重新构建网格。但 Refresh/F5 会杀死所有用户输入的信息。
- 还有什么?
这个问题常见吗?你如何解决类似的问题?最佳做法是什么?
【问题讨论】:
-
我已对您最近的 cmets 发表了补充评论。
标签: asp.net-mvc domain-driven-design