ASP.Net Passing ViewModel to View (Underlying entity framework) - c#

I am having problems passing a ViewModel into a view.
My ViewModel:
namespace ImpactDBASPNet.Models
{
public class ComputerInfoViewModel
{
public List<string> CompanyList { get; set; }
public tbl_computerinfo entitymodeleffort { get; set; }
}
}
Controller:
public ActionResult Index()
{
var tbl_computerinfo = db.tbl_computerinfo.Include(t => t.tbl_equipment);
tbl_computerinfo = tbl_computerinfo.Where(c => c.Company == "Test Company");
List<string> companylist = new List<string>();
companylist.Add("Hello1");
companylist.Add("hello2");
ComputerInfoViewModel model = new ComputerInfoViewModel();
model.CompanyList = companylist;
model.entitymodeleffort = tbl_computerinfo;
return View(model);
}
I'm doing this primarily because I need to pass a list for a dropdownlist in my view, so I need to pass in the entity framework model AND the list. The error I am getting is:
Error 1 Cannot implicitly convert type 'System.Linq.IQueryable<ImpactDBASPNet.Models.tbl_computerinfo>' to 'ImpactDBASPNet.Models.tbl_computerinfo'. An explicit conversion exists (are you missing a cast?) c:\impactdbaspnet\controllers\tbl_computerinfocontroller.cs 31 39 ImpactPortal

Property entitymodeleffort is typeof tbl_computerinfo but you assigning IEnumerable<tbl_computerinfo> to it, resulting in the error. You need to use FirstOrDefault() (or one of the variants - Single() etc.) that returns a single tbl_computerinfo object.
Change the code to
public ActionResult Index()
{
var tbl_computerinfo = db.tbl_computerinfo
.Include(t => t.tbl_equipment)
.Where(c => c.Company == "Test Company")
.FirstOrDefault();
List<string> companylist = new List<string>() { "Hello1", "Hello2" }; // save a few lines of code
ComputerInfoViewModel model = new ComputerInfoViewModel();
model.CompanyList = companylist;
model.entitymodeleffort = tbl_computerinfo;
return View(model);
}
Side note: Since companylist is used for a dropdownlist, you can make the property SelectList
public SelectList CompanyList { get; set; }
and
model.CompanyList = new SelectList(companylist);
and in the view
#Html.DropDownListFor(m => m.entitymodeleffort.SomeProperty, Model.CompanyList, ...)

Related

How to convert .List<anonymous> to .List<classname>?

To my Book entity I want to query to select required properties and return this as a list to the another List type of<BookModel> from which I'll be using as a model in my view. But in this line of code red squiggly line indicates error with the message :
cannot convert system.collections.generic.List<anonymous> to system.collections.generic.List<BookModel>
Of course I can use Select(b=> new BookModel{...}) class instead of anonymous type to creat list object type but I'm wondering if there's a way to return this without using BookModel, only by using anonymous type?
here is the property of List type that I want to return my anonymous type
public class HomeModel
{
public List<BookModel> PopularBooks { get; set; }
public List<BookModel> BestSales { get; set; }
}
and the action method that I'm making queries using lambda expressions.
public ActionResult HomeIndex()
{
HomeModel model = new HomeModel();
var bestSalebooks = db.Books.Where(b => b.IsApproved).OrderBy(b => b.DisplayNumber).Select(b => new
{
Id = b.Id,
Name = b.Name,
Description = b.Description,
Price = b.Price,
DateAdded = b.DateAdded,
CategoryId = b.CategoryId
}).ToList();
model.BestSales = bestSalebooks; //cannot convert system.collections.generic.List<anonymous> to system.collections.generic.Lis<BookModel>
return View(model);
}
In general, I would advise you to instantiate your required type. That is, if you need a BookModel, instantiate that instead of creating an anonymous type.
You are creating an anonymous type when you do the Select step.
Anyway you can also cast the anonymous type with your specific type by doing:
public ActionResult HomeIndex()
{
HomeModel model = new HomeModel();
var bestSalebooks = db.Books.Where(b => b.IsApproved).OrderBy(b => b.DisplayNumber).Select(b => (BookModel)(new
{
Id = b.Id,
Name = b.Name,
Description = b.Description,
Price = b.Price,
DateAdded = b.DateAdded,
CategoryId = b.CategoryId
})).ToList();
model.BestSales = bestSalebooks;
return View(model);
}
Doing this, you are creating a list of BookModel.

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.List1[<>f__AnonymousType22[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 http://asp.net/mvc.
</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
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.
Just a fetch a list of Product and take it to view then use the joined table like Product.Cateogry and loop in inner table.

SelectListItem checkboxes and autopopulate with using Contains()

I have a list of courses. If a user is assigned to a course, then I want that checkbox to be checked. How come the Contains() is not accepted?
ViewModel:
public class ViewUserViewModel
{
public List<Cours> Courses { get; set; }
public List<UserCours> UserCoursesList { get; set; }
public AspNetUser user { get; set; }
public IEnumerable<SelectListItem> CourseList { get; set; }
}
Controller:
[HttpGet]
public ActionResult ViewUser(string id)
{
ViewUserViewModel model = new ViewUserViewModel();
model.user = db.AspNetUsers.FirstOrDefault(U => U.Id == id);
//List all courses
List<Cours> allCourses = db.Courses.OrderBy(c => c.CourseName).ToList();
model.Courses = allCourses;
//List of courses the user is assigned to
//var selectedCourse1 = db.UserCourses.Where(uc => uc.UserId == id).ToList();
model.UserCoursesList = db.UserCourses.Where(uc => uc.UserId == id).ToList();
//checkbox list
model.CourseList = allCourses.ToList().Select(x => new SelectListItem()
{
//Selected = selectedCourse1.Contains(x.CourseID),
Selected = model.UserCoursesList.Contains(x.CourseID),
Text = x.CourseName,
Value = x.CourseID.ToString()
});
}
I'm thinking the Selected property will test if List has the value assigned, then it would return back true. Instead, it's a syntax error and has invalid arguments. How can I compare the CourseList to the UserCoursesList?
I think you should use LINQ Any method. You not posted you UserCours class definition, but I guess that it should have an ID, and might look like that:
public class Cours
{
public int Id { get; set; }
// Other properties
}
In this case your check for Selected property will be:
Selected = model.UserCoursesList.Any(uc => uc.CourseID == x.CourseID)
Some tips:
In this case it will be better to use some meaningful name instead of
x, for example course. It will improve readability of the code.
allCourses is already a list, you do not need to call ToList()
method again.
Updated code: thanks to Aleksandr
[HttpGet]
public ActionResult ViewUser(string id)
{
ViewUserViewModel model = new ViewUserViewModel();
//Which user
model.user = db.AspNetUsers.FirstOrDefault(User => User.Id == id);
//List all courses
model.Courses = db.Courses.OrderBy(Courses => Courses.CourseName).ToList();
//List of courses the user is assigned to
model.UserCoursesList = db.UserCourses.Where(UserCourses => UserCourses.UserId == id).ToList();
//checkbox list
model.CourseList = model.Courses.Select(Course => new SelectListItem()
{
Selected = model.UserCoursesList.Any(UserCourse => UserCourse.CourseId == Course.CourseID),
Text = Course.CourseName,
Value = Course.CourseID.ToString()
});
return View(model);
}

How to set two values in View()

How can set several objects in view?
public ActionResult Index()
{
var shops = this.context.shops.Select(q => new { q.id, q.name }).ToList();
var bikes = this.context.bikes.Select(q => new { q.id, q.name }).ToList();
return View(shops, bikes); // How to set two values in View()?
}
And parse in View()
#foreach (var r in Model.bikes)
{
<b>#r.name</b>
}
One way is to create a strong typed view model that contains both shops and bikes. Other option could be creating a Tuple and passing as a model to view. I would go first option.
Tuple
var tuple = new Tuple<shop, bike>(new shop(),new bike());
In you view
#Model Tuple<shop,bike>
You need create ViewModel
public class shopsAndbikes
{
public List<shop> shops {get;set;}
public List<bike> bikes {get;set;}
}
public ActionResult Index()
{
shopsAndbikes vm = new shopsAndbikes ()
{
var shops = this.context.shops.Select(q => new { q.id, q.name }).ToList();
var bikes = this.context.bikes.Select(q => new { q.id, q.name }).ToList();
}
return View(vm);
}
View:
#model shopsAndbikes
#foreach (var r in Model.bikes)
{
<b>#r.name</b>
}
#foreach (var r in Model.shops)
{
<b>#r.name</b>
}
Your Model-class should contain properties for both shops and bikes. That is if you use a strongly typed view, it looks that way. Otherwise you could add things to the ViewBag for use in the view.

Populate Result Set in SelectList MVC3

I have following SelectList declaration in CourseRegisterModel:
public class CourseRegisterModel
{
public StudentModel Student { get; set; }
public CourseModel Course { get; set; }
public IEnumerable<SelectListItem> CoursesList { get; set; }
public DateTime RegisterDate { get; set; }
}
In CourseController I am retrieving all available courses by calling wcf web service:
public ViewResult Index()
{
ServiceCourseClient client = new ServiceCourseClient();
Course[] courses;
courses = client.GetAllCourses();
List<CourseModel> modelList = new List<CourseModel>();
foreach (var serviceCourse in courses)
{
CourseModel model = new CourseModel();
model.CId = serviceCourse.CId;
model.Code = serviceCourse.Code;
model.Name = serviceCourse.Name;
model.Fee = serviceCourse.Fee;
model.Seats = serviceCourse.Seats;
modelList.Add(model);
}
return View(modelList);//RegisterCourses.chtml
}
I need to populate these courses in a dropdown on view RegisterCourses.chtml. How to put all records in selectlist in above code? Also how would i use that selectlist on view?
For starters, your RegisterCourses.cshtml needs to use:
#model <namespace>.CourseRegisterModel
Then, your controller code would be:
public ViewResult Index()
{
ServiceCourseClient client = new ServiceCourseClient();
Course[] courses;
courses = client.GetAllCourses();
CourseRegisterModel model = new CourseRegisterModel();
//model = other model population here
model.CourseList = courses.Select(sl => new SelectListItem()
{ Text = sl.Name,
Value = sl.CId })
.ToList();
return View(model);
}
And finally, back to your view (RegisterCourses.cshtml) - it should contain:
#Html.DropDownListFor(m => m.Course.CId, Model.CourseList)
Use the Html.DropDownList method: http://msdn.microsoft.com/en-us/library/dd492738(v=vs.108).aspx
Pass in the desired name of the drop down list as first argument, as second argument pass in your CourseList:
#Html.DropDownList("CoursesList", Model.CoursesList)

Categories