2

In my application I have created a base controller. All the other controller derives from BaseController

public class BaseController : Controller
{
    //
    // GET: /Base/
    public void Warning(string message)
    {
        TempData.Add(Alerts.WARNING, message);
    }
    public void Success(string message)
    {
        TempData.Add(Alerts.SUCCESS, message);
    }

    public void Information(string message)
    {
        TempData.Add(Alerts.INFORMATION, message);
    }

    public void Error(string message)
    {
        TempData.Add(Alerts.ERROR, message);
    }
}

No if I derive any other controller from BaseController it is possible to do this

public ActionResult Test()
{
   Success("This is a success Alert");
}

Now in _alert partial view I check the tempdata and growl it using Toastr.

_alerts partial view

@if (TempData.ContainsKey(Alerts.SUCCESS))
{
    foreach (var value in TempData.Values)
    {
        <script>    
            toastr.success("@value.ToString()");
        </script>

    }


}

@if (TempData.ContainsKey(Alerts.ERROR))
{
    foreach (var value in TempData.Values)
    {
        <script>

            toastr.error("@value.ToString()");
        </script>
    }
}

@if (TempData.ContainsKey(Alerts.INFORMATION))
{
    foreach (var value in TempData.Values)
    {
        <script>

            toastr.warning("@value.ToString()");
        </script>
    }
}

@if (TempData.ContainsKey(Alerts.WARNING))
{
    foreach (var value in TempData.Values)
    {
        <script>    
            toastr.warning("@value.ToString()");
        </script>
    }
}

this _alert partial view is renderd in my _layout view. Which is the main layout of the application.

All all the pages use that layout.

Problem:

The problem i'm facing is, once I send the message from controller, for example:

Success("This is a success message");

I get a nice message in browser. But everytime I go to next page I get the same message, as it still stays in my TempData.

What can I do to solve this issue?

I probably have to clear the temp data, but where?

I tried clearing TempData from view: but it doesn't allow me. I get error on browser saying I can only perform assign, increment, decrement and creating object and things like that but not TempData.Clear();. Also, it would not be good idea to perform clearing TempData in client side, would it?

Cybercop
  • 8,475
  • 21
  • 75
  • 135
  • TempData persists until read. Have a look at http://stackoverflow.com/questions/5953302/tempdata-is-not-clearing-as-expected it suggests changing the if statement from TempData.ContainsKey to TempData[] as this counts as a read – Cookie Mar 05 '14 at 10:14
  • @Cookie if TempData is cleared when it is read, then wouldn't TempData[Alerts.INFORMATION] != null be counted as reading? If its true then my message which i'm showing inside the if statement, what would happen to that? – Cybercop Mar 05 '14 at 10:19
  • "growl it using Toastr" <- As a developer it both amuses and concerns me that this is a valid line of text. – BenM Mar 05 '14 at 10:36
  • @Rondles Haha I didn't know the proper way to say it...Probably Alert using toastr? – Cybercop Mar 05 '14 at 10:37
  • No, please read the other anser, TempData.ContainsKey is not causing a read, accessing TempData with a key is – Cookie Mar 05 '14 at 10:40

2 Answers2

1

Could you try changing all usages of ContainsKey to a not null check?

Change this

@if (TempData.ContainsKey(Alerts.INFORMATION))
{
}

To

@if (TempData[Alerts.INFORMATION] != null)
{
}

Appearantly the TempData is only cleared when it is read and calling ContainsKey does not count as a read. Relevant Stackoverflow article here

Update: tried following code with success. Every time I reload, the TempData["S"] is null and refilled with the message (so it is the expected behaviour).

BaseController

public class BaseController : Controller
{
    public void Success(string message)
    {
        TempData.Add("S", message);
    }
}

HomeController

public ActionResult Test()
{
    Success("This is a success Alert");
    return View();
}

View

@if (TempData["S"] != null)
{
    foreach (var value in TempData.Values)
    {
        @value.ToString()
    }
}
Community
  • 1
  • 1
Bruno V
  • 1,721
  • 1
  • 14
  • 32
  • if TempData is cleared when it is read, then wouldn't `TempData[Alerts.INFORMATION] != null` be counted as reading? If its true then my message which i'm showing inside the if statement, what would happen to that? – Cybercop Mar 05 '14 at 10:19
  • I gave it a shot, but now my message doesn't show up. – Cybercop Mar 05 '14 at 10:20
  • I tried the code myself and for me it works with the not null check, see my updated answer. – Bruno V Mar 05 '14 at 10:42
  • Also thing to keep in mind `Furthermore, if you use RedirectResult or RedirectToRouteResult, they will persist even if they are read.` So in that case would it still work if you use `RedirectResult` or `RedirectToRouteResult` as return type? – Cybercop Mar 05 '14 at 10:44
1

This seems to have done the trick

@if (TempData.ContainsKey(Alerts.SUCCESS))
{
    foreach (var value in TempData.Values)
    {
        <script>    
            toastr.success("@value.ToString()");
        </script>

    }
    TempData.Remove(Alerts.SUCCESS);

}

but I still don't know if it is a good idea to clear TempData from view like I have done.

Suggestions?

Cybercop
  • 8,475
  • 21
  • 75
  • 135