sydneyos
sydneyos

Reputation: 4557

TempData not working for second request in MVC4

I have never seen this before and am stumped. I have the following controller sequence:

    /// <summary>
    /// Helper method to store offerId to TempData
    /// </summary>
    /// <param name="offerId"></param>
    private void StoreOfferInTempData(string offerId)
    {
        if (TempData.ContainsKey(SelectedOfferKey))
            TempData.Remove(SelectedOfferKey);
        TempData.Add(SelectedOfferKey, offerId);
    }

    [HttpPost]
    [AllowAnonymous]
    public virtual ActionResult Step1(MyViewModel model)
    {
        if (ModelState.IsValid)
        {
            StoreOfferInTempData(model.SelectedOfferId);
            return RedirectToAction(MVC.Subscription.Register());
        }

        MySecondViewModel model2 = new MySecondViewModel { OfferId = model.SelectedOfferId };
        return View(model2);
    }


    [HttpGet]
    [AllowAnonymous]
    public virtual ActionResult Register()
    {
        string offerId = TempData[SelectedOfferKey] as string; //we get a valid value here
        ... error handling content elided ...

        RegisterViewModel model = new RegisterViewModel { OfferId = offerId };

        return View(model);
    }

    [HttpPost]
    [AllowAnonymous]
    public virtual ActionResult Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            CreateCustomerResult result = CustomerService.CreateAccount(model.Email, model.NewPassword);
            if (result.Success)
            {
                ... content elided; storing customer to Session ...                    
                MyMembershipProvider.PersistUserCookie(result.Principal, true);

                //need to store our selected OfferId again for use by the next step
                StoreOfferInTempData(model.OfferId);
                return RedirectToAction(MVC.Subscription.Payment());
            }

            model.ErrorMessage = result.ErrorMessage;
        }

        return View(model);
    }


    [HttpGet]
    public ActionResult Payment()
    {
        string offerId = TempData[SelectedOfferKey] as string; //this is null???

        ... content elided ...

        return View(model);
    }

The first round of storage to TempData behaves as expected. The value is present in the subsequent HttpGet method and is marked for deletion such that it is no longer there when I go to add it again. However, on the third HttpGet method, it returns null.

I have tried using different Keys for each round with no change. I can assure you that at no time other than those displayed am I checking TempData, so I see no way the value would be marked for deletion somehow. Also, it fails in the Payment method whether it has an [AllowAnonymous] attribute or not (so not due to any http to https switch or anything like that.

Seems like it must be something very simple, but my searches have turned up nothing. Any help greatly appreciated.

UPDATE: On further inspection, it seems my whole context is hosed on this step, for some reason. We're using IoC in the controllers, but none of the IoC-instantiated items are there. The mystery deepens.

Upvotes: 5

Views: 4868

Answers (3)

Steve
Steve

Reputation: 352

Use TempData.Keep("key") to retain values between multiple post-backs

Upvotes: 0

sydneyos
sydneyos

Reputation: 4557

Aha! Well, this is obscure enough that I hope it helps someone else. Turns out, I had forgotten to run my T4MVC.tt file after creating the Payment() actions, so the RedirectToAction taking an MVC.Subscription.Payment() action was not instantiating the controller properly. I'm not clear on all the underlying magic here, but if you run into this and are using T4MVC.tt, make sure you ran it!

Comments on why this would be are welcome.

Upvotes: 1

Brad Christie
Brad Christie

Reputation: 101604

The lifespan of TempData is only until it's read back out or the next request has processed (which ever comes first). You shouldn't be relying on TempData if you're going in to two (or three) requests. Instead, use the session or a database.

The purpose of TempData is to hand-off information between requests not to perpetuate until you clear it (that's what sessions are for).

Upvotes: 3

Related Questions