MVC PRG 模式 - 传递模型
MVC PRG pattern - passing a model around
我在我的 MVC 项目中使用 PRG 模式 (Post-Redirect-Get)。这个想法是,您不会 return 从您的操作中查看,而是在成功时 POST 您完全重定向到另一个视图,该视图执行 Get(可能在数据库上)以取回保存的值并重新显示它们(想想 "Save Successful" 页面)。
就我而言,我没有数据库来保存保存的详细信息,我想知道一种可靠的存储方式,然后在下一页获取保存的详细信息。
我在做
RedirectToAction("Success", myViewModel)
我的理解是错误的,尤其是因为它具有 URL 栏中的所有值。我需要做的是
RedirectToAction("Success")
然后以某种方式取回值,构建视图模型并将其提供给视图。
我知道有 ViewBag、TempData、ViewData 和 Session,但没有在各种情况下进行大量测试,我不知道哪一个适合我的情况。静态对于面向 public 的网站显然没有好处。
如果在没有数据库的情况下做PRG,数据持久化的方式是什么?或者如果用户确实返回和转发,我可以简单地抛出某种错误并重定向吗?
非常感谢。
编辑:示例场景 - 汽车保险。用户访问站点,填写个人详细信息并点击提交。下一页显示了选项(第三方、盗窃、自愿超额等),选择它们后,将通过 AJAX 拨打电话以获取报价。
所有个人详细信息随选项一起发送。但是没有用户帐户,也没有任何内容写入数据库(数据保护法 - 除非获得许可,否则我们不会存储数据,如果他们只是浏览,询问会让他们失望)。
更新:我们确定的解决方案如下:
详细信息 POST 操作构建了一个 OptionsViewModel。它被放入 TempData。
RedirectToAction("Options") 被调用。
在 Options 操作中我们得到 viewmodel
OptionsViewModel viewModel = (OptionsViewModel)TempData.Peek("MyViewModel"); // .Peek preserves the value
如果 viewmodel 为 null,我们将 RedirectToAction() 返回到 Details。否则我们 return 选项视图。
除了它创建的难看的查询字符串之外,RedirectToAction("Success", myViewModel)
可能会失败,因为 (1) 您可能超过查询字符串限制(这会引发异常)或 (2) 如果您的模型包含以下属性复杂的对象或集合,这些属性将在 GET 方法中 null
。
ViewBag
和 ViewData
不适合在方法之间传递值 - 它们用于将数据从控制器传递到视图(参考 this article)
不清楚为什么你没有某种永久存储,但如果没有它,你将需要 TempData
或 Session
在请求之间临时存储数据。
TempData
使用 Session
但它只持续一个请求,所以如果你用它来将模型传递给 Success()
方法,并且用户刷新浏览器,模型将是 null
,尽管您可以使用 .Peek
或 .Keep
来覆盖该行为(请参阅 this question/answer)。
就个人而言,我从不使用 Session
(并且只使用 TempData
来传递非关键数据,例如指示成功的一次性消息)并且会考虑将数据保存在某个地方,例如保存到xml 重定向之前的文件,以便可以在 GET 方法中再次读取它。
我在我的 MVC 项目中使用 PRG 模式 (Post-Redirect-Get)。这个想法是,您不会 return 从您的操作中查看,而是在成功时 POST 您完全重定向到另一个视图,该视图执行 Get(可能在数据库上)以取回保存的值并重新显示它们(想想 "Save Successful" 页面)。
就我而言,我没有数据库来保存保存的详细信息,我想知道一种可靠的存储方式,然后在下一页获取保存的详细信息。
我在做
RedirectToAction("Success", myViewModel)
我的理解是错误的,尤其是因为它具有 URL 栏中的所有值。我需要做的是
RedirectToAction("Success")
然后以某种方式取回值,构建视图模型并将其提供给视图。
我知道有 ViewBag、TempData、ViewData 和 Session,但没有在各种情况下进行大量测试,我不知道哪一个适合我的情况。静态对于面向 public 的网站显然没有好处。
如果在没有数据库的情况下做PRG,数据持久化的方式是什么?或者如果用户确实返回和转发,我可以简单地抛出某种错误并重定向吗?
非常感谢。
编辑:示例场景 - 汽车保险。用户访问站点,填写个人详细信息并点击提交。下一页显示了选项(第三方、盗窃、自愿超额等),选择它们后,将通过 AJAX 拨打电话以获取报价。
所有个人详细信息随选项一起发送。但是没有用户帐户,也没有任何内容写入数据库(数据保护法 - 除非获得许可,否则我们不会存储数据,如果他们只是浏览,询问会让他们失望)。
更新:我们确定的解决方案如下: 详细信息 POST 操作构建了一个 OptionsViewModel。它被放入 TempData。 RedirectToAction("Options") 被调用。 在 Options 操作中我们得到 viewmodel
OptionsViewModel viewModel = (OptionsViewModel)TempData.Peek("MyViewModel"); // .Peek preserves the value
如果 viewmodel 为 null,我们将 RedirectToAction() 返回到 Details。否则我们 return 选项视图。
除了它创建的难看的查询字符串之外,RedirectToAction("Success", myViewModel)
可能会失败,因为 (1) 您可能超过查询字符串限制(这会引发异常)或 (2) 如果您的模型包含以下属性复杂的对象或集合,这些属性将在 GET 方法中 null
。
ViewBag
和 ViewData
不适合在方法之间传递值 - 它们用于将数据从控制器传递到视图(参考 this article)
不清楚为什么你没有某种永久存储,但如果没有它,你将需要 TempData
或 Session
在请求之间临时存储数据。
TempData
使用 Session
但它只持续一个请求,所以如果你用它来将模型传递给 Success()
方法,并且用户刷新浏览器,模型将是 null
,尽管您可以使用 .Peek
或 .Keep
来覆盖该行为(请参阅 this question/answer)。
就个人而言,我从不使用 Session
(并且只使用 TempData
来传递非关键数据,例如指示成功的一次性消息)并且会考虑将数据保存在某个地方,例如保存到xml 重定向之前的文件,以便可以在 GET 方法中再次读取它。