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.
Related
This question already has answers here:
Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1> in C#
(2 answers)
Closed 5 years ago.
I am storing the returned items to the var type and then trying it to bind with the list object which is of model class type. But while doing so it gives an error saying that,
cannot implicitly convert type
System.collections.generic.list<AnonymousType> to
System.Collections.Generic.List<MyService.Models.EmpModel>
Please help me resolve this issue.
public IEnumerable<EmpModel> GetEmpDetailsById(int id)
{
var EmpList = (from a in EmpDet
where a.EmpId.Equals(id)
select new { a.EmpId, a.Name, a.City });
List<EmpModel> objList = new List<EmpModel>();
objList = EmpList.ToList(); // gives error here
return objList;
}
You can do this in one statement
return (from a in EmpDet
where a.EmpId.Equals(id)
select new EmpModel
{ EmpId = a.EmpId,
Name = a.Name,
City = a.City
}).ToList();
}
The type of the objList is List<EmpModel> but you are returning a List of anonymous type. You can change it like this:
var EmpList = (from a in EmpDet
where a.EmpId.Equals(id)
select new EmpModel { EmpId = a.EmpId, Name = a.Name, City = a.City });
And if you still get error probably it is because you cannot project onto a mapped entity then you need to create a DTO class with needed properties from the EmpModel entity like this:
public class TestDTO
{
public string EmpId { get; set; }
public string Name { get; set; }
}
And then you can:
select new TestDTO { EmpId = a.EmpId, Name = a.Name }
I am in the process of loading all the products belonging to unique categories on an index page with the request product/index/[Category ID].
I have a ProductViewModel class which contains implicit methods to convert types between the two and also a Product entity model class. The implicit method to convert a Product entity to a ProductViewModel contains the method to convert a byte to a base64 string and I use this in my controller successfully to create new categories and products.
public class ProductViewModel
{
public int Id { get; set; }
[Required, Display(Name="Product Name")]
public string Name { get; set; }
[Required, DataType(DataType.Upload)]
public HttpPostedFileBase Image { get; set; }
public string OutputImage { get; set; }
[Required]
public Decimal Price { get; set; }
public static byte[] ConvertToByte(ProductViewModel model)
{
if (model.Image != null)
{
byte[] imageByte = null;
BinaryReader rdr = new BinaryReader(model.Image.InputStream);
imageByte = rdr.ReadBytes((int)model.Image.ContentLength);
return imageByte;
}
return null;
}
// ViewModel => Model | Implicit type Operator
public static implicit operator Product(ProductViewModel viewModel)
{
var model = new Product
{
Id = viewModel.Id,
Name = viewModel.Name,
Image = ConvertToByte(viewModel),
Price = viewModel.Price
};
return model;
}
// Model => ViewModel | Implicit type Operator
public static implicit operator ProductViewModel(Product model)
{
var viewModel = new ProductViewModel
{
Id = model.Id,
Name = model.Name,
OutputImage = string.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(model.Image)),
Price = model.Price
};
return viewModel;
}
}
However when passing a model containing all products belonging to a unique category ID to be displayed on the products View, I am not able to implicitly convert a byte to a string. The method that I use as an alternative is not accepted with the error:
LINQ to Entities does not recognize the method 'System.String Format(System.String, System.Object)' method, and this method cannot be translated into a store expression.
The Model in the Controller is the following:
var products = (await db.Categories.Where(c => c.Id == id).Select(p => p.Products.Select(x => new
ProductViewModel { Id = x.Id, Name = x.Name, OutputImage = (string.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(x.Image))), Price = x.Price})).ToListAsync());
return View(products);
The Model type I give the View is the following:
#model List<IEnumerable<ValueVille.Models.ProductViewModel>>
you can't use string.Format() in a LINQ expression instead of that you can use it in Name setter :
public class ProductViewModel {
public string Name{
get
{
return this.Name;
}
set{
this.Name = value;
this.OutputImage = string.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(value))
}
}
}
and in the controller :
var products = (await db.Categories.Where(c => c.Id == id).Select(p => p.Products.Select(x => new
ProductViewModel { Id = x.Id, Name = x.Name, Convert.ToBase64String(x.Image))), Price = x.Price})).ToListAsync());
I initially assumed you could still assign a byte[] to a string property, to have a byte[] value inside your setter and convert from byte to string inside the setter. If the property is a string, the value assigned to this property must be already a string.
A property assignment is NOT a conversion so it will never work as long as you try to assign directly x.Image which is a byte array to OutputImage which is a string.
You could keep the Image property as a byte array and to have an ImageHelper such as http://www.itorian.com/2012/10/html-helper-for-image-htmlimage.html
You would keep a byte array in your model :
Image = x.Image
And so you would pass this byte array to this helper.
Here I'm writing logic in class file and implementing in a controller. When I'm trying to implement the code in the controller it's throwing an error as "cannot assign void to an implicitly-typed local variable"
public void Getass()
{
var xx = from n in db.Accessors
join cn in db.Countrys on n.CountryID equals cn.CountryID
select new
{
n.Name,n.Id,n.CountryID,
cn.CountryName};
}
Dummy.cs
public JsonResult tt()
{
var sss= objrepo.Getass();
return new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Getass should return the collection but it is an anonymous type. Either create it in the method making the call
public JsonResult tt()
{
var xx = from n in db.Accessors
join cn in db.Countrys on n.CountryID equals cn.CountryID
select new
{
n.Name,
n.Id,
n.CountryID,
cn.CountryName
};
return Json(xx, JsonRequestBehavior.AllowGet);
}
or create a class to hold the result
public class MyModel {
public string Name { get; set; }
public string Id { get; set; }
public string CountryID { get; set; }
public string CountryName { get; set; }
}
public IList<MyModel> GetAccessors()
{
var xx = from n in db.Accessors
join cn in db.Countrys on n.CountryID equals cn.CountryID
select new MyModel
{
Name = n.Name,
Id = n.Id,
CountryID = n.CountryID,
CountryName = cn.CountryName
};
return xx.ToList();
}
public JsonResult tt()
{
var sss= objrepo.GetAccessors();
return Json(sss, JsonRequestBehavior.AllowGet);
}
You'll need to create a concrete type to return that from your method. void means the method doesn't return anything, and you can't use var as a return type.
So your choices are:
Create a concrete type and have your query create objects of that type (and change your return type to IEnumerable<{type}> or similar
Put the query from Getass inside the tt method so you can use an anonymous type.
you can't return a void type and expecting a result that you can assign to a variable
more you are creating an anonymous type by doing this
select new {
n.Name,n.Id,n.CountryID,
cn.CountryName};
if you want to return it oops,
you can't return an anonymous type because you haven't the name at compilation time. c# will assign an arbitrary name once compiled so you have to use object type
You can only return object, or container of objects, e.g. IEnumerable<object>, IList<object>, etc.
I am trying to make a jquery auto complete where I use a label and value like in this post which means that I need my json in the form of
{ label: 'label text', value: 'value text' }
However I am filtering a list of Employees which is a class with the following structure:
public sealed class Employee
{
public string Name { get; set; }
public string PersonnelNumber { get; set; }
public int RecID { get; set; }
public string Email { get; set; }
}
So I tried the following Linq to get the format of label, value I needed:
var jsonResult = employees
.SelectMany(emp => new { label = emp.Name, value = emp.RecID })
.ToList();
Where employees is a list of Employee objects but it is throwing up an build error of
Error 1 The type arguments for method 'System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
How do I fix this to get the Name and RecID in a new list of objects with label and value as their output?
I think you just want to use Select here:
var jsonResult = employees
.Select(emp => new { label = emp.Name, value = emp.RecID })
.ToList();
SelectMany is for "flattening" a group of collections. Since you just have a single collection just use Select:
var jsonResult = employees.Select(emp => new { label = emp.Name, value = emp.RecID })
.ToList();
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, ...)