Mike Bruno
Mike Bruno

Reputation: 634

Problem populating the ViewBag using TempData & Redirect

I've inherited an MVC project and I'm having some trouble as I am very new to MVC and web development in general.

The project contains a Controller Action method which generates a view. This method can either be called when the user accesses the view directly via the UI, or to regenerate the view after the user has clicked a button on the view to perform an action. If the view is regenerated after an action is performed, a verification message needs to appear on the page.

In the cshtml file, we have the following in MainWindow.cshtml, which only renders the table in the conditional if a string named "SavedMessage" exists in the ViewBag and is not null or empty:

@{ string actionResult = ViewBag.SavedMessage; }
@if (!string.IsNullOrEmpty(actionResult))
{
    <tr>
         <td>
             @actionResult
         </td>
    </tr>
}

In the Action method, I'm attempting to use the TempData object to transfer the string value to the Action which generates the view:

public partial class ApproveController : Controller
{
    const string IDX_ACTIONRESULT = @"ActionResult";

    public ActionResult MyAction(FormCollection collection)
     {
         try
         {
             string result_success = @"Action completed successfully";
             //Do stuff
             TempData[IDX_ACTIONRESULT] = result_success;
             return RedirectToAction("MainWindow");
         }
         catch (Exception e)
         {
             Logger.reportException(e);
             throw e;
         }
     }
 }

In the Action which generates the view, we load the value stored in TempData into a variable, and then test to see if the variable contains anything. If the variable is not null, I am attempting to load whatever it contains into the ViewBag.

Create View Action:

public partial class ApproveController : Controller
{
    public ActionResult MainWindow()
    {
        //Do Stuff
        var actionResult = TempData[IDX_ACTIONRESULT];
        if (actionResult != null)
        {
            Log.info("Action Result Message: " + actionResult);
            ViewBag.SavedMessage = actionResult;  
        }
        else
            Log.info("Action Result Message is NULL");


        return View();
    }
}

Possible lead: When the MainWindow() method is called through UI rather than Redirect from MyAction(), my log indicates that actionResult is null, however, when it is called via Redirect from MyAction(), actionResult is an empty string. This leads me to believe that MyAction() is populating TempData with something but I can't see why it doesn't contain the string I'm assigning in MyAction().

Anyone see a smoking gun here?

Upvotes: 5

Views: 621

Answers (2)

Mike Bruno
Mike Bruno

Reputation: 634

I needed to use a combination of TempData and the ViewBag to accomplish my goal. Here's what I did:

Worker Action Here, we just assign a string value to TempData[IDX_ACTIONRESULT] based on whether or not the action succeeds. Instead of throwing the exception, we'll log the exception and then report failure using this TempData attribute

public partial class ApproveController : Controller
{
    const string IDX_ACTIONRESULT = @"ActionResult";

    public ActionResult MyAction(FormCollection collection)
     {
         try
         {
             //Do stuff
             TempData[IDX_ACTIONRESULT] = @"Action completed successfully";
             return RedirectToAction("MainWindow");
         }
         catch (Exception e)
         {
             Logger.reportException(e);
             TempData[IDX_ACTIONRESULT] = @"The Action failed. Please contact your system administrator for assistance";
         }
     }
}

Create View Action When we build the view, we'll check to see if the attribute TempData[IDX_ACTIONRESULT] has an assigned value. If so, we'll read that value and assign it to ViewBag.SavedMessage.

public partial class ApproveController : Controller
{
    public ActionResult MainWindow()
    {   
        if (TempData[IDX_ACTIONRESULT] != null)
            ViewBag.SavedMessage = TempData[IDX_ACTIONRESULT].ToString();

        //Build the rest of the view

        return View();
    }
}

The empty string that I referenced in the Possible Lead portion of my question was attributed to the previous developer's code. He was simply reading the HTTP response message from a RESTful API call into the return value of a method. As it happens, that particular API returns an empty message on success. So, it seems that I've been chasing my tail for a few days :)

Upvotes: 0

Matti Price
Matti Price

Reputation: 3551

TempData uses Session storage to persist the data. My guess is that you haven't enabled session as it doesn't come by default any more I don't believe.

You need to add services.AddSession(); and app.AddSession(); to your startup code in order to enable it.

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.1#installing-and-configuring-session

Upvotes: 0

Related Questions