具有不同会话 mvc 的多个浏览器选项卡

Multiple browser tabs with different sessions mvc

该项目允许客户为各种类型的风险项目投保 (wheelchair/vehicle/scooter)。为每个风险项目创建了不同的路线(因为对每种类型提出了不同的问题)。目前可以选择一个风险项目,然后客户填写他们的所有信息,获得报价,然后接受保单(通过 credit/debit 卡支付)。创建此应用程序是为了每份保单仅投保一个风险项目。如果客户只想投保一个风险项目,所有这些都可以正常工作。如果客户端然后 select 以确保不同的风险(或另一个)项目,问题仍然存在,因为浏览器现在持有先前请求的会话。

我需要找到一种方法来允许报价和接受不同(或相同)的风险项目,而不会干扰以前的政策开始(支付)。 当客户选择一个风险项目(来自不同的网站)时,它将导航到风险项目的第一个起点,打开一个不同的选项卡。是否可以为每个选项卡维护一个会话?

这就是完成的...

注册路线(文件引用 Global.asax)

    public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapMvcAttributeRoutes();
        routes.MapRoute(
            name: "Scooter",
            url: "Scooter/{action}/{id}",                
            defaults: new { controller = "Mobility", action = "All", id = UrlParameter.Optional}
        );
        routes.MapRoute(
            name: "Wheelchair",
            url: "Wheelchair/{action}/{id}",
            defaults: new { controller = "Mobility", action = "All", id = UrlParameter.Optional }
        );
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "ComingSoon", id = UrlParameter.Optional }
        );

    }
}

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        BundleMobileConfig.RegisterBundles(BundleTable.Bundles);

        //Add a required data annotation that relies on the value of another property to set the field as required
        DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute),typeof(RequiredAttributeAdapter));
    }

正在创建会话:

    #region Helpers
    private static T GetSession<T>(string key)
    {
        object value = HttpContext.Current.Session[key];

        if (value == null)
            return default(T);
        else
            return ((T)value);
    }

    private static void SetSession(string key, object value)
    {
        HttpContext.Current.Session[key] = value;
    }

    public static void ClearQuoteSession()
    {
        HttpContext.Current.Session.Clear();
        HttpContext.Current.Session.Abandon();
    }

    public static string GenerateBuyMapCode()
    {
        var holderKey = Guid.NewGuid();

        var polMapCode = "BB-" + holderKey;

        return polMapCode.Trim();
    }

以下方法允许使用 cookie 创建会话。

    public static PolicyBase CreateNewPolicyBase(Enums.RiskType type)
    {
        var polBase = new PolicyBase();
        polBase.Insured = new InsuredViewModel();
        polBase.RiskMeItems = new List<RiskItemMeModel>();
        *Irrelevant code removed*
        polBase.SessionKey = GenerateBuyMapCode();
        polBase.BrowserSession = HttpContext.Current.Session;

        *Irrelevant code removed*
        return polBase;
    }

    #region Session INIT
    public static string QuoteKey
    {
        get { return GetSession<string>("QuoteKey"); }
        set { SetSession("QuoteKey", value); }
    }
    public static AusEnums.RiskType RiskType
    {
        get { return GetSession<AusEnums.RiskType>("RiskType"); }
        set { SetSession("RiskType", value); }
    }

    public static AusEnums.QuoteArea Area
    {
        get { return GetSession<AusEnums.QuoteArea>("QuoteArea"); }
        set { SetSession("QuoteArea", value); }
    }

    public static PolicyBase PolicyBase
    {
        get { return GetSession<PolicyBase>("PolicyBase"); }
        set { SetSession("PolicyBase", value); }
    }

    public static SSMultiPremium MultiPremium
    {
        get { return GetSession<SSMultiPremium>("MultiPremium"); }
        set { SetSession("MultiPremium", value); }
    }

web.config

    <sessionState mode="InProc" cookieless="UseDeviceProfile" regenerateExpiredSessionId="true" timeout="20" />

机动性和机动性风险项目起点不同,以下为机动性起点(以客户为准)

    [HttpGet]
    [OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
    public ActionResult Insured()
    {
        //We need to determine the direction

        SessionHelper.GetRoutePath((Route)ControllerContext.RouteData.Route);
        var polBase = SessionHelper.PolicyBase;
        HttpCookie userCookie = new HttpCookie("BBCookieCheck");
        userCookie["Name"] = "BB";
        userCookie.Expires.AddDays(1); // cookie will expire after 1 days
        Response.Cookies.Add(userCookie);

        var viewModel = new InsuredViewModel();
        if (polBase != null)
        {
            viewModel = polBase.Insured;
            viewModel.Title = polBase.Insured.Title;
        }

        viewModel.riskType = SessionHelper.RiskType;
       *Irrelevant code removed*
        return View(viewModel);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Insured(InsuredViewModel model)
    {
        *Irrelevant code removed*
        //create a new quote object and save the relevant fields
        var polBase = SessionHelper.PolicyBase;
        if (model.Id == 0)
        {
            polBase = SessionHelper.CreateNewPolicyBase(model.riskType);
           *Irrelevant code removed*
        }
     }

看来您的用例可能会受益于 cookieless session 状态跟踪。 看起来你也差不多在那里。

    <sessionState cookieless="UseUri" regenerateExpiredSessionId="true" timeout="20" />

UseDeviceProfile 几乎意味着任何现代浏览器都会使用 cookie。但是,如果您专门将其锁定为 UseUri,您可能会获得更好的结果。

在这种情况下,您的 GetSession<string>("XXX") 可能变得多余,因为每个会话只与一个策略流程相关