Reputation: 5086
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.
Upvotes: 1
Views: 20431
Reputation: 1244
Personally I really can only think of one (but I am sure there a few more instances) reason to use view data is so that I can fetch some data on client without making callback to server. When you make an HTTP request you typically make a query against the database and render the results.
Very rarely do you need to hide/store some other data that you may or may not need based on the rendering to the point that you do not wish to callback the database for more data. Besides, things may have changed on the database making the stored data useless. Session state or unique user data would likely be stored in some other method but tbat might be a reason to use it.
Upvotes: 0
Reputation: 31862
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>
.
Upvotes: 9
Reputation: 180868
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.
Upvotes: 1
Reputation: 2002
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
Upvotes: 0