如何在 MVC 下创建简洁且 RESTful 的向导?

2023-11-22

我尝试在构建应用程序时尽可能保持 RESTful,但我不确定的一件事是如何创建一个向导式工作流程,保持 RESTful 和简洁。

以多页面注册流程为例。

选项1:我可以为每个步骤创建一个控制器,并在用户到达该步骤(或返回该步骤)时调用 new 或 edit。我以step1_controller、step2_controller等结束...

选项2:我可以创建一个控制器,并使用参数、会话变量、状态机等来跟踪它们在注册过程中的位置。所以我有signup_controller/step?id=1

第一个选项是严格的 REST,但不是很简洁,并且以一些额外的控制器结束。第二个选项更简洁,但破坏了 REST,我愿意这样做,但我不会掉以轻心。

有更好的选择吗?

我正在 ruby​​ on Rails 中工作,但这个问题适用于其他 MVC 实现,例如 ASP.NET MVC


如果你在这里应用一些DDD逻辑,它补充了MVC中的“M”,UI的状态(注册进度)属于应用程序层,它可以直接与域和基础设施层(四层:UI,应用程序,域和基础设施)。 DDD 的概念让你首先“思考”如何在代码中解决问题。让我们逐步完成这个...

这是进度条

这里要保持的状态是注册的步骤或进度。因此,我的第一步是记录进度或“步骤”。例如,第 1 步:获取用户名/密码,第 2 步:获取电子邮件。在这种情况下,我将应用逻辑将模型“移动”到下一步。最有可能使用 RegistrationService 上的 NextStep() 方法 (RegistrationService.NextStep())。

啊,不过是属于App层的

我将在应用程序层创建一个名为 RegistrationService 的服务。我会在这里放置一个名为 NextStep() 的方法。但请记住,域不会保存此处模型的状态。在这种情况下,您希望将状态集中在应用程序层。因此,在这种情况下,NextStep() 不会作用于模型对象(因为它不是域职责的一部分),而是作用于 UI。因此,您需要一些东西来保留注册过程的状态。

远离领域模型,ViewModel 怎么样?

现在我们知道必须保留 UI 中某些内容的状态。 MVC 允许一个称为 ViewModel 的概念(在 ASP.NET MVC 中,不确定 RoR 称之为什么)。 ViewModel 表示将由视图和/或部分视图显示的模型。

ViewModel 将是保存该对象状态的绝佳位置。我们将其命名为 RegistrationProgressViewModel() 并在其上添加 NextStep() 方法。当然,这意味着应用程序层必须保留 RegistrationProgressViewModel 的位置,并且应用程序层将根据 NextStep 操作更改其内部结构。如果很复杂,您可能需要在应用程序层创建一个 RegistrationProgressService() 并将 NextStep() 放在其中以抽象您的逻辑。

如何传递 ViewModel?

最后一部分是如何跟踪该对象的状态。由于 Web 应用程序是无状态的,因此您必须通过应用程序以外的其他方式来保留控制权。在这种情况下,我将恢复为:1)将 ViewModel 序列化到客户端并让客户端来回传递它,或者 2)保留 ViewModel 的服务器端副本,并来回传递某种类型的标识符到客户并返回。

这是一个值得思考的好例子,因为我自己还没有这样做过。对于#2,保存此 ViewModel 状态的最安全、最保险的方法是通过基础设施层将其持久化(是的,APp 层可以直接与基础设施层对话)。对我来说,这似乎是一项繁重的工作,因为某些东西可能会消失,而且我的数据库中会有部分注册。

但是,#2 会将用户的私人信息(用户名、密码、电子邮件、CC # 等)全部保留在服务器端,而不是来回传递。

终于有答案了!

因此,在经历了这些之后,我们得出了以下结论:

  • 在应用层创建一个RegistrationProgressViewModel()。
  • 在应用程序层中使用 NextStep(ViewModel vm) 方法创建 RegistrationProgressService()。
  • 当NextStep()执行时,通过基础设施层将ViewModel持久化到数据库中。

这样,您就不必跟踪视图或 UI 本身上的“step?id=2”,因为随着您的前进,ViewModel 会不断更新(已验证、已验证、持久化到数据库)。

因此,您的下一个关注点是在用户界面中“前进”。使用步骤或命名步骤,使用 1 个控制器即可轻松完成此操作。

我很抱歉,但我正在下面编写 C# 代码,因为那是我的语言。

public class RegistrationController : Controller
{
  // http://domain.com/register
  public ActionResult Index()
  {
    return View(new RegistrationProgressViewModel);
  }

  // http://domain.com/register
  // And this posts back to itself.  Note the setting 
  // of "CurrentStep" property on the model below.
  //
  public ActionResult Index(
      RegistrationProgressViewModel model)
  {

    // The logic in NextStep() here checks the
    // business rules around the ViewModel, verifies its
    // authenticity, if valid it increases the
    // ViewModel's "CurrentStep", and finally persists
    // the viewmodel to the DB through the Infrastructure
    // layer.
    //
    RegistrationProgressService.NextStep(model);

    switch (model.CurrentStep)
    {
      case 2:
        // wire up the View for Step2 here.
        ...
        return View(model);
      case 3:
        // wire up the View for Step3 here.
        ...
        return View(model);
      case 4:
        // wire up the View for Step4 here.
        ...
        return View(model);
      default:
        // return to first page
        ...
        return View(model);
    }
  }
}

您会注意到,这将验证模型内部状态的“业务逻辑”抽象到 RegistrationProcessService.NextStep() 方法中。

好的练习。 :)

最后,您的“RESTful”url 是一个漂亮且干净的 POST 到:/register,它需要一个填充了特定属性的 ViewModel。如果 ViewModel 无效,/register 不会前进到下一步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 MVC 下创建简洁且 RESTful 的向导? 的相关文章

随机推荐