【问题标题】:Real World MVC - Dealing with Forms真实世界 MVC - 处理表单
【发布时间】:2010-11-28 19:22:42
【问题描述】:

我仍然对 MVC 应该如何工作感到有些困惑。

假设我有一个销售小部件的网站。我有一个列表页面/widgets/list 和一个产品页面/widgets/product/123

这两者都可以使用widget 控制器并调用listproduct 方法——到目前为止已经足够简单了。假设我还有其他几个控制器来处理各种事情。

现在我在我的标题中添加了一个时事通讯注册框 - 即在网站的每个页面上。 这将如何运作?我知道它应该提交给/newsletter/signup

但是如果出现错误(比如您没有正确填写您的电子邮件地址)会发生什么?它应该显示您所在的任何页面(例如/widgets/list),但newsletter 控制器需要运行。 widget 控制器不知道 newsletter 控制器,所以我不能把代码放在那里......这应该如何工作?

编辑:请不要使用 AJAX - 我可以更容易理解。将此视为禁用 javascript 时的后备。

编辑 2:任何涵盖此类事情的示例或教程将不胜感激

编辑 3:视图是否允许调用操作?例如标头可能会调用Newsletter->index()

【问题讨论】:

    标签: model-view-controller language-agnostic design-patterns


    【解决方案1】:

    我不明白为什么每个页面上的时事通讯框的错误消息都必须呈现在同一页面中。如果您有一个发布到另一个操作的页面 - 与当前视图完全无关(例如 - 搜索),那么没有理由在原始页面中显示错误消息。您会在同一页面上显示成功消息吗?那会在哪里处理呢?

    时事通讯表单的错误消息应显示在时事通讯专用的视图中。例如,看看它是如何在 Stackoverflow 中完成的 - 进入搜索框并且不输入任何内容,只需按 Enter。这是一种错误,因为您没有指定要搜索的内容。 Stackoverflow 会带你到一个不同的页面来解释搜索是如何工作的。

    现在为什么要这样做?原因很简单 - 用户在某个页面上并选择参与与当前页面无关的活动,因此没有理由将它们留在那里。

    【讨论】:

    • 虽然我可以想象 OP 想要返回到原始视图,但我可能也会选择您建议的方法。
    • 补充一点:要保留用户上次所在位置的“标记”,您可以使用 cookie 或将查询字符串附加到 URL。例如:/newsletter/signup?return_to=widgets/list
    • +1 在我看来,将用户重定向到另一个控制器以通知成功/失败是完全可以接受的。
    【解决方案2】:

    向新闻通讯表单添加一个字段,用于存储当前页面的 URL。 如果在提交时事通讯期间发生错误,请检索 URL 并重定向到该页面。只要您将错误信息放在正确的位置,它就应该被您说的包含在每个页面中的时事通讯表格中提取出来。

    【讨论】:

      【解决方案3】:

      有一个很好的以 ASP.net MVC 为中心的 tutorial 描述了在 MVC 环境中包含小部件(可重用组件)的方法。

      基本思想是使用自己的请求管道设置小部件 - 不要将它们合并到一个组合控制器/视图中,这会破坏 MVC 的可维护性。

      【讨论】:

        【解决方案4】:

        您必须将错误消息放在页面控制器(包括“子控制器”newsletter)可以获取的某个全局位置。

        在 AJAX 的情况下,您可以让 newsletter 控制器与可见的 DIV 对话(因为您没有重新加载整个页面)。为此,您需要在 AJAX 请求完成时调用的页面中的一段 JavaScript 获取字符串并将其放在您想要的任何位置。

        【讨论】:

          【解决方案5】:

          我的 MVC 经验更实用,更少“书上所说的”,但这里是:

          您将有一个基控制器类(在 CakePHP 中 - 这是我最熟悉的 - 它称为 AppController),它是所有其他控制器的子类。此类将实现您所说的所有“全局”内容。

          实际例子:

          在我的AppController 类中,框架定义了一个beforeFilter() 回调,它基本上在每次页面加载时执行。这是我检查注册表是否已提交并适当处理的地方。如果注册以某种方式出现问题,我会在会话中添加一些内容,以表明同样多的内容,我的视图将简单地检查是否存在源自时事通讯模型的错误列表,如果存在,则显示它们。

          这可能比你所要求的更重一些,理论上更轻,但我没有接受过任何这些废话的正式培训,所以这是我最好的:)

          【讨论】:

            【解决方案6】:

            对于应该返回一些验证错误等的小部件 - 使用 partial requests(或来自 MvcContrib 的子控制器)+ AJAX。

            【讨论】:

              【解决方案7】:

              我所做的是让每个表单都自己发布。在控制器中,我检查是否设置了 post 变量;如果是这样,我会进行验证。如果验证成功,我会重定向到另一个页面。如果失败,表单页面只会重新加载错误消息。这使它变得容易并减少了代码重复。见这里:

              **in controller**:
              
              If post variable is set:
                  validate form
              
                  if form is validated:
                      redirect to new page (or whatever)
                  else:
                      add error messages to the $data variable of the view
                  endif
              
              endif
              
              //$data contains whatever information you'd normally pass to the view.
              //if there was a validation error, the messages are added to the $data variable
              show view with $data variable
              

              如您所见,流程总是落入单个视图加载语句。但是,如果验证成功,您将被带到另一个页面。

              【讨论】:

              • 如果我有一个现有的网站,其中有 10 个控制器,每个控制器有 5 个操作,这是否意味着如果我在标题中添加时事通讯注册,我必须编辑 50 个函数?
              • 那将是它发布到单独页面的例外情况。大多数表单不会出现在多个页面上,只会出现在新闻通讯、登录和注册等内容上。总体来说,上面的还是很有效的。
              【解决方案8】:

              如何在提交给 /newsletter/signup 控制器的页面中添加一个隐藏字段,其中包含控制器完成后去哪里的 URL,即当前页面(或者您可以使用引用 http 标头)。

              然后,此控制器将错误消息列表或成功消息添加到要由视图呈现的对象列表中,然后再转发到上面隐藏字段指定的控制器。然后,此控制器添加要在视图中显示的对象列表(例如小部件列表)。

              然后在视图中,您可以显示来自 newsletter 控制器的错误消息(如果存在)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-11-24
                • 1970-01-01
                • 1970-01-01
                • 2011-03-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多