【问题标题】:ASP.NET MVC persisting data across multiple wizard steps using database tablesASP.NET MVC 使用数据库表跨多个向导步骤持久化数据
【发布时间】:2016-09-08 01:55:35
【问题描述】:

在 ASP.NET MVC 中通过几个向导步骤使用数据库表实现数据持久性的最佳方法是什么?

目前,我们正在使用会话在多个向导步骤/视图中保存大量数据。我们遇到了一个问题,我们怀疑会话超时是罪魁祸首。出于这个原因,我们决定用数据库表替换会话。

到目前为止,我们已经确定我们需要以下内容:

  • 当用户点击第一页时,一个唯一的 id/token(可能 数据库主键)生成将确定数据在哪里 存储在整个工作流程中。此 id/token 使用 URL,如果可能的话,这样我们就不需要重新实现会话

  • 每个向导视图/步骤的单独表格。我们在每个操作中实现了测试存储在会话中的向导步骤对象的逻辑,以确保用户不能跳过工作流中的步骤。将数据分成不同的表而不是单个表,使用数据库数据持久性实现类似的测试会更容易

  • 在与提供的 id/token 关联的记录中的某处存储过期时间戳以模拟会话超时,例如,如果当前日期时间大于存储的日期时间戳,则在处理发布的表单时拒绝请求

  • 使用实体框架推拉数据

我们只是很难弄清楚如何在代码中实现这一点。我们遇到了http://www.4guysfromrolla.com/webtech/041600-2.shtml,它有点帮助,但并没有真正解释如何在 ASP.NET MVC 控制器中实现它。

我们在下面提供了一个 sn-p 代码,以帮助我们了解我们当前如何使用会话来做事:

控制器

[HttpGet]
public ActionResult StepOne() {
    StepOneViewModel stepOneModel;
    WizardViewModel wizard = (WizardViewModel)Session["Wizard"];

    if(wizard == null || wizard.StepOne == null)
        stepOneModel = new StepOneViewModel();

    else
        stepOneModel = wizard.StepOne 

    return View();
}

[HttpPost]
public ActionResult StepOne()
{
    //validate and store data into wizard session object
}

public ActionResult StepTwo()
{
    StepTwoViewModel stepTwoModel;
    WizardViewModel wizard = (WizardViewModel)Session["Wizard"];

    if(wizard == null || wizard.StepOne == null)
        return RedirectToAction("StepOne");

    if(wizard.StepTwo == null)
        stepTwoModel = new StepTwoViewModel();

    else
        stepTwoModel = wizard.StepTwo;

    Session["Wizard"] = wizard;

    return View();
}

向导模型

public WizardViewModel
{
   public StepOne { get; set; }
   public StepTwo  { get; set;}
}

实施这种方法的最佳方式是什么?我们如何创建/跟踪这个确定数据从哪里提取的唯一令牌?我们如何测试用户是否完成了之前的步骤并且没有尝试跳过?任何关于我们如何实现这种方法的控制器代码/想法都值得赞赏。

【问题讨论】:

  • 为什么不使用单例类在您的应用中存储和持久化数据?

标签: c# asp.net-mvc database session datapersistance


【解决方案1】:

以下是我们过去实施类似模式的方式。 我在这里假设你的用户没有在系统中注册(如果他们是那么容易一点)

  1. 向导的第一步是收集用户的电子邮件地址。

  2. 我们为此会话生成一个唯一令牌并将其嵌入到 url 并通过电子邮件发送给用户。用户可以使用它随时返回并完成工作流程。您需要使令牌足够大,这样人们就不能随便猜测随机令牌。

注意:我们实际上生成了一个令牌 ID,我们在内部使用它来映射到工作流程过程。我们还生成一个嵌入到 url 中并发送给用户的哈希。

  1. 我们使用普通的实体表,而不是为每个步骤使用单独的表,在这些表的顶部,我们有一个表将用户令牌链接到实体数据并指示状态,我们用它来确定他们离巫师有多远。这意味着您有一个基本路线,该路线确定当前步骤并转移到该步骤的正确路线。

  2. 定期清理令牌,即删除超过 2 周的令牌。向用户发送电子邮件的 url 仍然有效,但会将他们带到新的工作流程,并且令牌会被重新用于新会话。

  3. 最后,如果工作流完成,我们可以从系统中删除令牌。

如果用户已经注册到系统中,那么你不需要给他们发邮件,你只需要以某种方式将你的工作流链接到用户。

【讨论】:

  • 在将令牌/哈希嵌入到 URL 中时,我们也在考虑同样的事情。你是如何做到这一点的?带有自定义路由的基于属性的路由?目前我们的申请表不直接与数据库交互。表单数据被序列化并发送到我们负责创建数据库记录的财务软件。
  • 在我们的例子中,它是一个非常通用的 MVC 应用程序。在我们用于该函数的基本路由的控制器中,它检查令牌,如果找到它,它会确定它的状态,并使用Redirect() 重定向到正确的路由。这发生在View 被调用之前,因此用户看不到任何闪烁或重绘。他们只是在正确的位置结束。
  • 感谢您的指导。我无法理解我们如何将令牌保留在 URL 中。如果我们在第一步生成一个令牌,我们如何使用 http:/....../{token}/Apply/StepOne 之类的 URL 在整个工作流程中将其持久化,或者您是否以某种方式从控制器内部生成了一个查询字符串行动。
  • 哦,所以我们使用哈希基本上将 tokenId 加载到我们的会话中。我们可以使用它来获取正确的数据。这个想法是,如果用户离开页面的时间过长并且超时,我们会显示一条消息说它已经超时,并使用我们通过电子邮件提供的 url 继续该过程。您可能可以将 url 中的哈希作为参数保留,但在各处传递它可能会有点混乱。
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 2013-01-27
相关资源
最近更新 更多