我的申请中有一个注册页面。它有 3 个状态和 1 个错误状态(如果出现任何错误):
- 填写基本信息
- 选择套餐
- 说谢谢
- 错误
现在我想在这里使用状态模式。首先,我创建了一个可以的控制台应用程序。现在我想在我的 MVC 应用程序中实现这个逻辑,但我对结构感到困惑。我的意思是我需要多少视图、模型和控制器,以及在哪里放置我的逻辑。
我的申请中有一个注册页面。它有 3 个状态和 1 个错误状态(如果出现任何错误):
现在我想在这里使用状态模式。首先,我创建了一个可以的控制台应用程序。现在我想在我的 MVC 应用程序中实现这个逻辑,但我对结构感到困惑。我的意思是我需要多少视图、模型和控制器,以及在哪里放置我的逻辑。
1个控制器:RegistrationController
6种动作方法:
这是让你思考的粗略代码:
public class RegistrationController : Controller
{
public ActionResult Index()
{
RegistrationState model = RegistrationState.Init();
// just display the "Fill Basic Info" form
return View(model);
}
[HttpPost]
public ActionResult Index(RegistrationState data)
{
// process data and redirect to next step
this.TempData["RegState"] = data;
if (!this.ModelState.IsValid || data.State == State.Error)
{
// error should handle provided state and empty one as well
return RedirectToAction("Error");
}
return RedirectToAction("Package");
}
public ActionResult Package()
{
RegistrationState data = this.TempData["RegState"] as RegistrationState;
if (data == null)
{
return RedirectToAction("Error");
}
// get packages and display them
IList<Package> model = this.repository.GetPackages();
return View(new Tuple.Create(data, model));
}
[HttpPost]
public ActionResult Package(RegistrationState data)
{
// process data blah blah blah
}
// and so on and so forth
....
}
如您所见,您仍然需要编写一些与 MVC 相关的代码来对状态更改采取行动。在我的示例中,一切都在操作方法中完成。但也可以使用动作过滤器。如果您无法提出可以为许多不同状态对象提供服务的通用动作过滤器,那么最好只在动作方法中编写代码。
如果你对 Asp.net MVC 足够了解,你可以更进一步,编写一个状态机 ControllerFactory,它可以在某种意义上与路由一起工作:
{StateObjectType}/{State}
因此,ControllerFactory 将能够将视图数据解析为已知的状态对象类型并将执行传递给特定的操作。根据状态。这将使它成为一个特别适合 Asp.net MVC 应用程序的状态机。
更重要的问题当然是您是否可以使用这种模式创建整个应用程序,或者它的某些部分应该像这样工作。您当然可以结合这两种方法并为每种方法提供适当的路由。
你应该非常小心你如何定义你的错误状态,因为输入无效的字段数据不应该导致错误状态,而是在视图中实际显示在无效数据字段旁边的数据验证错误(即,作为 13 提供的无效日期/13/1313)。您的错误状态应仅用于与用户输入无关的实际对象状态错误。那会是什么超乎我的想象。
正如我在评论中提到的,您应该查看一些 Asp.net MVC 介绍视频,您将了解验证在 Asp.net MVC 中的工作原理。也比较简单的东西。
这种状态模式不是普通的 Asp.net MVC 开发人员会使用的,因为它很可能比采用普通方法更复杂代码。先分析再做决定。Asp.net MVC 在代码方面非常干净,因此在其上添加额外的抽象可能会让人感到困惑。而且您的域模型(状态类)很可能具有更复杂的代码,例如带有数据注释的简单 POCO。
在您的情况下,数据验证也会更复杂(当与数据注释一起使用时),因为您的对象应该根据其状态进行验证,这可能在状态之间有所不同。POCO 对象的验证总是相同的。这可能意味着我们可以使用更多的类,但它们更小、更简单且更易于维护。
我认为你在混淆状态。状态示例如下:
现在这些状态中的每一个都有一个页面:
如果用户因为将某些字段留空而无法注册,他们将处于第一个状态,您将不得不显示一些验证消息。
因此,至少我将拥有一个名为 Register 的控制器和以下操作方法: