Search code examples
c#asp.net-mvctempdata

Intermittent results with ASP.NET MVC TempData - sometimes it loses it's value


In an ASP.NET MVC app, I have a controller action which calls business layer to add an entity.

If for business reasons, the entity could not be added, an Error property is set to true along with a description.

If true, I set a TempData key to the error message and then redirect to a view which has code to display the error stored in TempData if it exists. Sometimes the conditional block is shown and sometimes not.

Here is the relevant code in my controller

var added = ModelHelper.CreateSessionCode(model);

if(added.Error)
{
    TempData["SessionCodesMessage"] = model.ErrorDescription;
    TempData["MessageClass"] = "alert-danger";
}
else
{
    TempData["SessionCodesMessage"] = "Created session code";
    TempData["MessageClass"] = "alert-success";
}

return RedirectToAction("Index");

Then in my view I have this code:

@if (TempData["SessionCodesMessage"] != null)
{
    <div class="alert @TempData["MessageClass"] alert-dismissable" style="margin-top: 8px;">
        <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
        @(TempData["SessionCodesMessage"])
    </div>
}

And it seems to be inconsistent when the message is displayed or not. Could this be a browser cache issue or similar? From stepping through the code I can confirm that the execution goes into both controller conditional blocks depending on the result of adding the entity.


Solution

  • Okay so, TempData is like ViewData but with a difference. It can contain data between two successive requests, but after that they are destroyed.

    If you want to keep TempData value then you can use Keep:

    TempData.Keep()
    

    In your case:

    var added = ModelHelper.CreateSessionCode(model);
    
    if(added.Error)
    {
        TempData["SessionCodesMessage"] = model.ErrorDescription;
        TempData.Keep("SessionCodesMessage");
        TempData["MessageClass"] = "alert-danger";
        TempData.Keep("MessageClass");
    }
    else
    {
        TempData["SessionCodesMessage"] = "Created session code";
        TempData.Keep("SessionCodesMessage");
        TempData["MessageClass"] = "alert-success";
        TempData.Keep("MessageClass");
    }
    
    return RedirectToAction("Index");
    

    OR

    You can also use Peek if you want to be explicit about every time you want to retrieve it without having it deleted.

    var added = ModelHelper.CreateSessionCode(model);
    
    if(added.Error)
    {
        //second request, PEEK value so it is not deleted at the end of the request
        TempData["SessionCodesMessage"]; = "Created session code";
        object sessioncodevalue= TempData.Peek("SessionCodesMessage");
        TempData["MessageClass"]; = "alert-success";
        object messageclassvalue= TempData.Peek("MessageClass");
    }
    else
    {
        //second request, PEEK value so it is not deleted at the end of the request
        TempData["SessionCodesMessage"]; = "Created session code";
        object sessioncodevalue= TempData.Peek("SessionCodesMessage");
        TempData["MessageClass"]; = "alert-success";
        object messageclassvalue= TempData.Peek("MessageClass");
    }
    
    return RedirectToAction("Index");
    

    You can use Peek when you always want to retain the value for another request. And use Keep when retaining the value depends on additional logic.

    You can refer to this article for more information on these functions and how you can use them in your View: https://www.c-sharpcorner.com/UploadFile/ansh06031982/using-tempdata-peek-and-keep-in-Asp-Net-mvc/