MVC 5 Partial View using ViewData or TempData Not Working?

I'm calling an ActionResult which then returns a Partial View with a foreach ViewData / TempData containing a list of strings. So far the app runs without any errors and I don't see any messages showing in the Partial View either.

The goal is to have the Partial View show a building list of completed tasks like so:
   * New Cars Import Successful
   * Used Cars Import Successful

Here's what I have so far.
[View]
   <div>
       @using (Ajax.BeginForm("Import", "Excel", new AjaxOptions ....
        <input id="submit" type="submit" .... 
   </div>
   
   <div>    
        @{ Html.RenderPartial("_ImportStatus"); }    
  </div>

[Partial View]
   <h4>Excel Import Status:</h4>

<ul>
    @{ List<string> list = TempData["list"] as List<string>;
           if (list != null && list.Count > 0)
           {
               foreach (var item in list)
              {
                  <li>item</li>
              }
           }
       }
</ul>
  
[Controller]
   public async Task<ActionResult> Import (viewModel model)
   {
         foreach (var tab in model.Sheets) //Excel
         {
              if (tab.Name.Contains("NewCars"))
              {
                    await GetNewCars(model);
              }

              if (tab.Name.Contains("UsedCars"))
              {
                    await GetUsedCars(model);
              }
         }
    }

     public async Task<ActionResult> GetNewCars(viewModel model)
     {
         // Entity import code

            List<string> list = new List<string>();
            list.Add("New Cars Import Successful!");

            TempData["list"] = (List<string>)list;
            
            return PartialView("_ImportStatus");
        }

       public async Task<ActionResult> GetUsedCars(viewModel model)
       {
         // Entity import code

            List<string> list = new List<string>();
            list.Add("Used Cars Import Successful!");

            TempData["list"] = (List<string>)list;
            
            return PartialView("_ImportStatus");
        }

Open in new window

WorknHardrAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Bob LearnedCommented:
I prefer to use a view model, rather than ViewData/TempData, so that I can get Intellisense.  You would need to pass in the view model as a @model argument, and then you should be able to access the properties in the partial view.
0
WorknHardrAuthor Commented:
Understood, I like using Models. To be clear, both GetNewCars and GetUsedCars will be called and each adds its message to the same persisted List<String>. I don't think the same Partial View will show the entire list of messages. I'm unsure how to make a static List<sting> which will keep each message added to it.
0
Bob LearnedCommented:
"I don't think the same Partial View will show the entire list of messages. "
This is a case of not understanding the entire problem.  Can you show me how the data hierarchy?
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

WorknHardrAuthor Commented:
Okay, using a Model now. I'm working with the Status string now just for testing.

   public class viewModel
    {        
          public List<string> StatusList { get; set; }
          public string Status { get; set; }
    }

I've also setup a simple Partial View to see if it will display a simple Status string.
My goal is to add several messages to the StatusList

[Controller]
  public async Task<ActionResult> GetUsedCars(viewModel model)
       {
          try
          {
              // Entity import code
          }
          catch{}

           model.Status = "Used Cars Import Successful!";
            
            return PartialView("_ImportStatus", model); //debugger shows the correct values for model.Status
        }

[View]
  [View]
   <div>
       @using (Ajax.BeginForm("Import", "Excel", new AjaxOptions ....
        <input id="submit" type="submit" .... 
   </div>
   
   <div>    
        @{ Html.RenderPartial("_ImportStatus", Model); }    
  </div>

[Partial View]
   @model viewModel

<h4>Import Status:</h4> //this shows in main view

@Html.LabelFor(m => m.Status); //this never shows anything

Open in new window

0
Bob LearnedCommented:
How are you generating the viewModel class?
0
WorknHardrAuthor Commented:
I don't what you mean by 'generating'.

I think the big problem is using the Ajax.BeginForm which calls the 'Import' Action. It only has one return when the entire Action is run. It returns a result to it's TargetID. So GetNewCars and GetUsedCars methods must return to the Import Action on code completion. Then the TargetID gets the final List<string>. This is not my goal...

[View]
   @using (Ajax.BeginForm("Import", "Excel", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "result"}))
    {}
    <div id="result"></div>


[Controller]
   public async Task<ActionResult> Import (viewModel model)
   {
         model.StatusList = new List<string>(); // using the List<string.> again

         foreach (var tab in model.Sheets) //Excel
         {
              if (tab.Name.Contains("NewCars"))
              {
                    string message = await GetNewCars(model);
                    model.StatusList.Add(message);
              }

              if (tab.Name.Contains("UsedCars"))
              {
                    string message = await GetUsedCars(model);
                    model.StatusList.Add(message);
              }
         }
       return Content(model.StatusList));
    }

     public async Task<String> GetNewCars(viewModel model)
     {
          // Entity import code
           
            return "New Cars Import Successful"
        }

       public async Task<String> GetUsedCars(viewModel model)
       {
          // Entity import code

           return "Used Cars Import Successful"
        }
0
Bob LearnedCommented:
Maybe a better word would be "constructing"...I still don't see where the viewModel instance is constructed.
0
WorknHardrAuthor Commented:
The first View has the button click is build like so.

[Index View]
  @model viewModel
  @{
         ViewBag.Title = "";
     }

     <div>
       @using (Ajax.BeginForm("Import", "Excel", new AjaxOptions ....
        <input id="submit" type="submit" .... 
   </div>
   
   <div>    
        @{ Html.RenderPartial("_ImportStatus", Model); }     
  </div>

[index Action]
   viewModel model = new viewModel
   {
        Sheets = list
   };

[Models]
   public class viewModel
    {
        public string Name { get; set; }
        public List<Sheetss> Sheets { get; set; }
        public List<string> StatusList { get; set; }
        public string Status { get; set; }
    }

    public class Sheetss
    {
        public string Name { get; set; }
        public string Option { get; set; }        
    }

Open in new window

0
Bob LearnedCommented:
1) You create a view model with Sheets property set to a list.

2) You pass the view model to the partial view:

@{ Html.RenderPartial("_ImportStatus", Model);

3) You use the model in the partial view:

   @model viewModel

<h4>Import Status:</h4> //this shows in main view

@Html.LabelFor(m => m.Status); //this never shows anything

4) Put a breakpoint on this line, and check the value in Immediate Window:

@Html.LabelFor(m => m.Status); //this never shows anything

5) If it doesn't have any value, then work your way back through the call hierarchy, and check each point with breakpoints and checking values.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
WorknHardrAuthor Commented:
Okay, I'll take it from here, thx
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.