C# MVC多页表单丢失会话

C# MVC多页表单丢失会话,c#,asp.net-mvc-3,forms,session,tempdata,C#,Asp.net Mvc 3,Forms,Session,Tempdata,我有一个多页的表格用来收集线索。同一表单有多个版本,我们称之为活动。有些活动是3页表单,有些是2页,有些是1页。它们都共享相同的潜在客户模型和活动控制器等。有一个操作用于控制活动流,还有一个单独的操作用于将所有潜在客户信息提交到数据库中 我无法在本地复制此内容,并且有检查确保用户不能跳过页面。会话模式为InProc 这将在每次POST操作之后运行,该操作在会话中存储值: protected override void OnActionExecuted(ActionExecutedCont

我有一个多页的表格用来收集线索。同一表单有多个版本,我们称之为活动。有些活动是3页表单,有些是2页,有些是1页。它们都共享相同的潜在客户模型和活动控制器等。有一个操作用于控制活动流,还有一个单独的操作用于将所有潜在客户信息提交到数据库中

我无法在本地复制此内容,并且有检查确保用户不能跳过页面。会话模式为InProc

这将在每次POST操作之后运行,该操作在会话中存储值:

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        if (this.Request.RequestType == System.Net.WebRequestMethods.Http.Post && this._Lead != null)
            ParentStore.Lead = this._Lead;
    }
这是控制器中的Lead属性:

    private Lead _Lead;

    /// <summary>
    /// Gets the session stored Lead model.
    /// </summary>
    /// <value>The Lead model stored in session.</value>
    protected Lead Lead
    {
        get
        {
            if (this._Lead == null)
                this._Lead = ParentStore.Lead;

            return this._Lead;
        }
    }
问题发生在上述操作之间,在执行以下提交操作之前:

    [HttpPost]
    public virtual ActionResult Submit(Lead lead, string campaign, int page)
    {
        if (this.Session.IsNewSession || this.Lead.Submitted || !this.LeadExists)
            return RedirectToAction("Campaign", new { campaign = campaign, page = 0 });

        lead.AddCustomQuestions();
        MergeLead(campaign, lead, this.AdditionalQuestionsType, false);

        if (ModelState.IsValid == false)
            return View(GetCampaignView(campaign, page), this.Lead);

        var sharedLead = this.Lead.ToSharedLead(Request.Form.ToQueryString(false)); //Error occurs here and sends me an email with whatever values are in the form collection.
        EAUtility.ProcessLeadProxy.SubmitSharedLead(sharedLead);
        this.Lead.Submitted = true;
        VisitorTracker.DisplayConfirmationPixel = true;

        TrackLead(this.Lead, campaign, page, LeadType.Shared);

        return RedirectToAction(this.ConfirmationView);
    }
我们网站的每位访问者都会获得一个唯一的GUID visitorID。但是,当这些错误发生时,活动帖子和提交帖子之间的visitorID不同。因为我们在活动和提交操作期间通过TrackLead()方法跟踪每个表单提交,所以我可以看到会话在调用之间丢失,尽管每次发布后都会触发OnActionExecuted并将表单存储在会话中

因此,当出现错误时,我们在一个visitorID下得到一半表单,在另一个visitorID下得到表单的其余部分。幸运的是,我们使用了一个第三方服务,该服务在每次表单值更改时发送一个API调用,该表单值使用它自己的ID。这些ID在表单的前半部分和表单的其余部分之间是一致的,这是我从丢失的会话问题中保存线索的唯一方法

我还应该注意到,这在99%的情况下都很好

编辑: 我修改了代码,将lead对象显式存储在TempData中,并使用TempData.Keep()方法在后续请求之间持久化该对象。我只在我的3个站点中的1个站点部署了这种行为,但到目前为止还不错

我还尝试将会话中的lead对象直接存储在控制器操作中,即

Session.Add("lead", this._Lead);
它使用HTTPSessionStateBase,试图绕过包装类,而不是使用HTTPSessionState的HttpContext.Current.Session。正如预期的那样,这一修改在这个问题上没有什么不同

编辑#2: 今天早上查看电子邮件时,我注意到两个会话错误,尽管我将lead模型保存在TempData中。有什么东西导致会话被清除,很可能是某种应用程序池循环,但我还没有弄清楚。我可能要开始在SQL Server中存储会话

SessionStore.cs请求代码:

public static class SessionStore
{
    private static HttpSessionState Session
    {
        get { return HttpContext.Current.Session; }
    }

    public static T Get<T>(object name, T defaultValue)
    {
        var key = name.ToString();
        return SessionStore.Session.ContainsKey(key) ? (T)Session[key] : defaultValue;
    }

    public static void Set(object name, object value)
    {
        SessionStore.Session.Add(name.ToString(), value);
    }
}
公共静态类会话存储
{
私有静态HttpSessionState会话
{
获取{return HttpContext.Current.Session;}
}
公共静态T Get(对象名称,T defaultValue)
{
var key=name.ToString();
return SessionStore.Session.ContainsKey(key)-(T)Session[key]:defaultValue;
}
公共静态无效集(对象名称、对象值)
{
SessionStore.Session.Add(name.ToString(),value);
}
}

您能同时包含SessionStore代码吗?整个过程似乎非常脆弱且容易出错。如果用户在同一页面上打开两个选项卡,同时刷新或提交它们,会发生什么情况?看起来他们会覆盖彼此的线索。这就是使用Session的问题所在,它在用户可能打开的所有选项卡之间都会被撕碎。为什么不将lead存储在数据库中呢?这些网站与lead management/call center软件/iframe集成在一起(尽管这不是iframe特有的问题)。每位代表一次只能打开我们网站的一个实例,一次提交一个,但如果他们打开多个选项卡,开始填写表格,提交第一页,打开另一个选项卡,提交另一个第一页,返回第一个选项卡并提交,第一条线索将通过。第二个选项卡,如果试图提交,将重定向到第一个表单页面,它们必须重新开始。这不是一个问题,但我明白你的意思。我也试图通过打开多个选项卡来重现这个错误,就像你提到的,但一切都按预期进行。如果我开始填写表单,并通过浏览器清除缓存/cookies,然后尝试提交表单的第二页,这将重现错误。但代表们并没有这样做。今天,该网站获得了约2600名独立访客,并提交了约180份提交页面。不知道有多少page1表单提交。其中,有3个会话错误,低于平均值。将sessionState模式更改为SQLServer没有任何影响,我继续随机收到会话错误。不过,会话错误线索中的一小部分实际上进入了我们的数据库。
Session.Add("lead", this._Lead);
public static class SessionStore
{
    private static HttpSessionState Session
    {
        get { return HttpContext.Current.Session; }
    }

    public static T Get<T>(object name, T defaultValue)
    {
        var key = name.ToString();
        return SessionStore.Session.ContainsKey(key) ? (T)Session[key] : defaultValue;
    }

    public static void Set(object name, object value)
    {
        SessionStore.Session.Add(name.ToString(), value);
    }
}