.NET MVC3 中多页表单的最佳实践/设计

Posted

技术标签:

【中文标题】.NET MVC3 中多页表单的最佳实践/设计【英文标题】:Best practice/design for a multi-page form in .NET MVC3 【发布时间】:2012-09-02 17:09:07 【问题描述】:

我正在开发一个 Web 应用程序,该应用程序涉及用户填写跨多个页面的多步骤表单。表单顶部有标签式导航(这些链接不提交当前页面),底部有一个下一步按钮(提交)。我正在考虑几种处理表单提交/验证的策略:

    一个操作方法和每个表单页面的视图。当您点击下一步时,它会将表单提交给下一页的操作方法。如果出现验证错误,您将被重定向回上一页:

    网址是描述性的,可以复制粘贴 仅在错误情况下重定向 由于重定向没有表单数据,我们会丢失有关提交的上下文,从而难以显示某些错误消息 如果用户尝试访问他们尚未准备好的流程中的步骤,则相同的验证逻辑适用于重定向用户

    一个操作方法和每个表单页面的视图。当您点击下一步时,它会将表单提交给当前页面操作。如果存在验证错误,则返回相同的视图。否则,我们重定向到下一页操作:

    网址是描述性的,可以复制粘贴 重定向很常见(不确定这是否不好) 显示验证错误时,我们与表单提交在同一个请求中,因此我们可以完全访问无效输入 如果我们希望能够添加额外的上下文,例如,添加一个“上一个”按钮,该按钮也会提交

    一种适用于所有页面的操作方法。 URL 包含有关正在提交的步骤的附加上下文(例如 MyController/MyAction/step)。控制器消息根据验证和当前步骤选择要返回的视图页面。

    URL 不是描述性的(例如,如果我提交第 1 步以转到第 2 步,那么无论返回第 1 页(无效)还是第 2 页,用户看到的 URL 都是相同的 无重定向 显示验证错误时,我们与表单提交在同一个请求中,因此我们可以完全访问无效输入

    另一种方法我没有在这里列出

我试图列举我认为每种方法的一些优缺点,但我很想知道:

这些方法的其他优点和缺点是什么?我的正确吗?可以围绕我列出的一些缺点进行设计吗? 我应该使用解决此问题的标准方法吗?如果是,为什么它是标准方法?

【问题讨论】:

听起来您需要接受操作处理请求并返回(在大多数情况下)视图的概念。每个表单页面都有一个操作允许您拥有特定于该页面上的数据的视图模型。如果模型无效,该操作可以返回相同的视图,也可以返回下一页的视图。不需要重定向。您可以在form 中使用hidden 输入在页面之间传递上下文。 @HABO:但是如果我不重定向并且用户在第 1 页提交了无效的内容,那么即使返回的视图是页面的无效视图,他们也不会看到第 2 页的 url 1 个? 您的操作选择要返回的适当视图:第 1 页或第 2 页。如何决定取决于您。浏览器显示它得到的任何东西,但不需要通过重定向请求不同的页面。 【参考方案1】:

我强烈推荐选项 2,稍作修改。您可能还想考虑为每个操作/视图创建一个视图模型。如果您有一个跨越所有页面的模型,则将跨所有属性进行验证,这意味着即使用户只能在每个屏幕上编辑模型的一部分,他们也可能会收到他们看不到的属性的验证警告。我们最近在一个项目中这样做了,效果很好。您必须在后端进行一些数据操作才能将所有内容重新组合在一起,但最终还是值得的。

正如您所说,您的 URL 将是可深度链接的,这意味着用户可以复制/粘贴,更重要的是,他们可以将页面添加为浏览器中的收藏夹,让他们很容易回到同一个地方.在我看来,这使得选项 3 过时了。

您还将受益于您的所有导航逻辑都发生在一个地方这一事实。您必须将“向导”的状态存储在客户端(您当前所在的页面)上,以便您的控制器知道提交时要做什么。您需要分析向导的状态并决定用户下一步需要去哪里。如果您选择选项 1,您将不知道您“来自”哪里,并且服务器验证错误将难以显示给客户端。这是 POST - REDIRECT - GET 模式的一个很好的例子。每个页面将有 2 个操作,一个采用简单 id 的 GET 和一个采用更复杂模型的 POST。发布服务器,找出下一步去哪里,重定向到 GET。

最后,考虑您的上一个按钮只是直接链接到上一步,而不是提交表单。否则,用户可能会卡在无效步骤上。这发生在我们身上,而且效果很好。

希望这会有所帮助。祝你好运!

【讨论】:

您提到了 POST - REDIRECT - GET 模式。是否存在频繁重定向使页面转换感觉更慢的风险(尤其是因为我们在每次请求时从数据库加载模型的一部分)? 当然。这是你必须考虑的事情。由于网络的无状态特性,POST - REDIRECT - GET 非常有效。但是,如果性能是一个问题(查询速度慢等),那么您可能需要考虑另一种存储解决方案,例如 No-SQL 提供程序,或者在会话中存储对象。 每个视图一个模型,步骤 n 怎么知道步骤 1 和步骤 2 是否正确完成?例如,假设有人进入第三步然后离开站点/应用程序。大概他们的进度存储在会话中......但是让我们假设他们离开的时间足够长,以至于会话衰减。他们直接返回到第 3 页的书签。在我看来,每一步的“索引”操作都必须将之前的每一步从会话中拉回适当的模型并重新验证。在我看来,这在第 20 步会变得非常昂贵。 如果你不小心,它肯定会变得昂贵;但是,有人可能会争辩说,您希望它验证所有步骤,以确保它们没有以某种方式通过无效步骤。例如,如果您在第 10 步并且第 2 步无效,也许您不希望他们在第 10 步?解决方法当然是在您“发布”或您正在做的任何事情之前的最后一步简单地验证对象的整个状态。在我们的实现中,我们使用了很多 Lazy 来帮助提高性能。这样我们只有在实际步骤中才真正点击 DB。

以上是关于.NET MVC3 中多页表单的最佳实践/设计的主要内容,如果未能解决你的问题,请参考以下文章

markdown 表单设计最佳实践

使用 ADO.NET 为 MVC 3 应用程序设计 DAL 的最佳方法?

RESTful API 设计最佳实践

在mysql数据库中保存许多坐标的最佳设计实践?

基于ABP落地领域驱动设计-03.仓储和规约最佳实践和原则

如何将消息插入取决于会话值的视图。 ASP.NET MVC。最佳实践