views:

129

answers:

3

Hi All, I am new to MVC and facing one issue. I have a xml file and i am retrieving its value using Linq to xml and assigning it to ViewData. Controller.cs

           var res=from x in doc.Descendants("person")
                  select new 
                  {
                    Fname=x.Element("fname").Value,
                    Lname=x.Element("lname").Value

                  };
                   ViewData["Persons"]=res;

in View I am trying

         <% foreach (var item in ViewData["Persons"])   
                 { %>  


                   <li> <%= item.Fname %> </li>  


                 <% } %>  

but foreach (var item in ViewData["Persons"] is giving type casting error..what should be the exact type csting so that i can retrive values in the format item.Fname.

Thanks.

+7  A: 

Using ViewData, although possible, is not the most elegant way to pass information from controller to view. Using specific view model instead makes code easier and cleaner, and resolves casting issues.

Try defining model first:

public class ViewModelElement
{
    public string Fname { get; set; }
    public string LName { get; set; }
}


public class ViewModel
{
    public List<ViewModelElement> Elements { get; set; };
}

Then use your model in action:

public ActionResult ActionName()
{
  //get doc somehow
  var model = new ViewModel();

  //When querying by linq to xml, you can create ViewModelElement instead of anonymous class
  model.Elements = (from x in doc.Descendants("person")
      select new ViewModelElement
      {
        Fname=x.Element("fname").Value,
        Lname=x.Element("lname").Value
      }).ToList();

  return View(model);
}

Then use your model in view:

<% foreach (var item in model.Elements) { %>  
   <li> <%= item.Fname %> </li>  
<% } %> 

View has to inherit from System.Web.Mvc.ViewPage<ViewModel>.

LukLed
select new ViewModelElement is giving casting problem..it says cant convert from type Generic.Ienumerable to Generic.List
Wondering
@Wondering: You can add .ToList() when setting `Elements`. This is your problem? I corrected my solution.
LukLed
thanks.it worked.
Wondering
A: 

The default type in ViewData collection for a non-strongly typed view is object.

Your view is throwing an exception because it cannot automatically cast from object back to IEnumerable which LINQ queries return.

Change your loop to this and it should work fine:

  <% foreach (var item in (IEnumerable)ViewData["Persons"])   
                 { %>  


                   <li> <%= item.Fname %> </li>  


                 <% } %> 

By far the best advice is to strongly type your views so that you can do what LukLed suggested

thorkia
I am unable to retrive item.Fname..actually Fname is not coming in intellisense itself.
Wondering
A: 

The problem with your existing code is that you're projecting your data into an anonymous type with your Linq query, so there is no named type to cast to.

Assuming you had a named type (Person) to cast to (and you still wanted to use ViewData), your solution would be:

<% foreach (var item in (IEnumerable<Person>)ViewData["Persons"])

But inheriting your page from a strongly-typed ViewModel object is a better solution.

Robert Harvey