k.nisha Cuty k.nisha Cuty - 3 months ago 12
C# Question

Bind a Linq Lambda Select Many from Controller to view in MVC4? What are the Best ways to return in view

I am new to MVC by Linq. When I am working with Console application its working fine.

When i shift to Mvc Architecture, passing the values from controller to view i am getting error as

The model item passed into the dictionary is of type 'System.Collections.Generic.List

1[<>f__AnonymousType2
2[System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcApplication2.Models.Teams]'.

I know i am passing Objects as stringName,String and its expecting 'System.Collections.Generic.IEnumerable how to resolve this kind of issues

This Scenario happen for Multiple groupby and Selectmany in Linq .how to pass the value and get into bind for View . what is the Best approach.

i have put a foreach in Controller and return or else do the foreach iterations in view for selectMany,Groupby,Lookup etc.

Model

public Class Product
{
public string CategoryName {get; set; }
public int Productid { get; set; }
public List<String> Productname { get; set; }

public static List<Product> GetAllProductName()
{
var ListofProducts = new List<Product>
{
new Product { CategoryName = "Choclateid", Productid = 1, Productname = new List<string> { "DairyMilkshots", "DairyMilk Silk", "DairyMilkFruitsNuts" }},
new Product { CategoryName = "Vegetables", Productid = 2, Productname = new List<string> { "Tomoto", "Pototo", "Onion"}},
new Product { CategoryName = "Fruits", Productid = 3, Productname = new List<string> {"Apple", "Orange", "Strawberry"}},
};
return ListofProducts;
}
}


Controller

public ActionResult Home()
{
var ny = Product.GetAllTeamMembers()
.SelectMany(x => x.Productname, (category, withProductlist) =>
new { cat = category.CategoryName, PN = Productname })
.ToList();

return View(ny);
}


View

@model IEnumerable< MvcApplication2.Models.Product>

@{
ViewBag.Title = "Selectmany";
}

<h2>@ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
</p>
@{
foreach(var k in Model)
{
@K.CategoryName<br/>
@k.Productname<br/>
}
}


Console

var ny = Product.GetAllTeamMembers().SelectMany(x => x.Productname,
(category, withProductlist) =>
new { cat = category.CategoryName, PN = Productname };

foreach(var n in ny)
{
Console.WriteLine(n.cat + "\t" + "-" + n.PN);
}


Output


Choclate -DairyMilkshots DairyMilk Silk DairyMilkFruitsNuts

Vegetables - Tomoto,Pototo,Onion

etc

Answer

The problem is that your view is set to handle an explicit type:

@model IEnumerable< MvcApplication2.Models.Product>

But the LINQ method does not return a type of Product. You're actually returning an anonymous type with this portion of the LINQ statement:

(category, withProductlist) => new { cat = category.CategoryName, PN = Productname })

The new keyword helps identify that. Your console application works b/c the anynomous object has properties for PN and CategoryName but does not explicitly need a certain type.

Does that make sense?

As has been suggested, you should just pass in the values from the call Product.GetAllTeamMembers() to your view. Your view should then assign the values for the type. For example,

Controller:

public ActionResult Home()
{
   var ny = Product.GetAllTeamMembers();

   return view(ny);
}

View @model IEnumerable< MvcApplication2.Models.Product>

@{  
  foreach(var k in Model)
  {
     @K.CategoryName<br/>
     @k.Productname<br/>

  }                    

} }

EDIT

The best way to do what you want is to create a view model to contain the flattened information. This gives you the shape of the data as you want and allows you to use the model in your controller.

New View Model

public class ProductViewModel
{
    public string CategoryName { get; set; }
    public string ProductName { get; set; }
}

Controller Logic

var ny = Product.GetAllProductName()
.SelectMany(x => x.Productname, (category, withProductlist) =>
    new ProductViewModel
    {
        CategoryName = category.CategoryName,
        ProductName = withProductlist
    });

The View

@model IEnumerable<ProductViewModel>

The important part is in the select many clause, you're casting to a known type (ProductViewModel) instead of an anonymous type.