Solved

MVC 5 Partial View using ViewData or TempData Not Working?

Posted on 2014-10-09
10
1,387 Views
Last Modified: 2014-10-14
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

0
Comment
Question by:WorknHardr
  • 5
  • 5
10 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40372916
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
 

Author Comment

by:WorknHardr
ID: 40373257
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40373707
"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
 

Author Comment

by:WorknHardr
ID: 40374155
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40374178
How are you generating the viewModel class?
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:WorknHardr
ID: 40374400
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40377051
Maybe a better word would be "constructing"...I still don't see where the viewModel instance is constructed.
0
 

Author Comment

by:WorknHardr
ID: 40377397
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
 
LVL 96

Accepted Solution

by:
Bob Learned earned 500 total points
ID: 40380036
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
 

Author Closing Comment

by:WorknHardr
ID: 40380748
Okay, I'll take it from here, thx
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

I recently went through the process of creating a Calendar Control of events with the basis of using a database to keep track of the dates that are selectable, one requirement was to have the selected date pop-up in a simple lightbox.  At first this…
ASP.Net to Oracle Connectivity Recently I had to develop an ASP.NET application connecting to an Oracle database.As I am doing it first time ,I had to solve several problems. This article will help to such developers  to develop an ASP.NET client…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now