ASP.NET MVC : Empty Collection in model - c#

Hi,
I'am pretty new in ASP.NET MVC, and I have some problem.
I make some program that searching product in data base, if click
button "end", program show me list of my previously searched products.**
This is my code from controler:
private ProductManager pm = new ProductManager();
private PointOfSaleContext db = new PointOfSaleContext();
public ActionResult Detail(SearchProduct productCode)
{
if (!ModelState.IsValid)
{
return RedirectToAction("Index", "Home");
}
else
{
//searching product in data base
var searchingProduct = db.Products.Where(p => p.ProductId == productCode.Code).Single();
int id = searchingProduct.ProductId;
//add searched product to model
SingleProduct product = new SingleProduct();
product.product = searchingProduct;
//I send product Id to ProductManager method
pm.AddToList(id);
return View(product);
}
}
public ActionResult List()
{
//object of model
AllItems all = new AllItems();
//
all.productList = pm.list;
return View(all);
}
This is my class, where I created Product list
public class ProductManager
{
private PointOfSaleContext db = new PointOfSaleContext();
public List<product> list;
public ProductManager()
{
list = new List<product>();
}
public void AddToList(int id)
{
var product = db.Products.Where(p => p.ProductId == id).SingleOrDefault();
list.Add(product);
}
}
View of controller List:
#model PointOfSale.ViewModel.AllItems
<ul>
#foreach (var p in Model.productList)
{
<li> #p.ProductName <li>
}
</ul>
My ViewModel:
public class AllItems
{
public List<Product> productList { get; set; }
}
public class SingleProduct
{
public Product product;
}
Problem is those, that I can't read data from ICollection in AddToList View.
More precisely- Model in View List is empty and I don't know why.

Related

EF MVC4 returning null after updating entries in many to many relationship

I have a many to many relationship b/w drivers and vehicle entity, at the time of driver creation, many vehicles can be assigned to a driver, it works fine, but when I want to edit and update records I am getting null collection of vehicles,
Here are my Models :
public class Driver {
public int driverId {get;set;}
public string Name {get;set;}
public virtual ICollection<Vehicle> Vehicles {get;set;}
}
public class Vehicle {
public int Vehicle_Id {get;set;}
public string Vehicle_Type_Name {get;set;}
public virtual ICollection<Driver> Drivers {get;set;}
}
Here I define the relationship:
modelBuilder
.Entity<Driver>()
.HasMany<Vehicle>(d => d.Vehicles)
.WithMany(d => d.Drivers).Map(
cs =>
{
cs.MapLeftKey("DriverId")
.MapRightKey("VehicleId")
.ToTable("DriversVehicles");
});
And my driver View Model
public class DriverViewModel
{
public DriverViewModel()
{
SelectedVehicles=new List<int>();
VehicleList = new List<Vehicle>();
}
public Driver driver { get; set; }
public List<int> SelectedVehicles { get; set; }
public List<Vehicle> VehicleList { get; set; }
}
And here is driver Edit() Controller Action :
public ActionResult Edit(int id = 0)
{
DriverViewModel DriverVm = new DriverViewModel();
var list = db.vehicles.Select(
v => new { v.Vehicle_Id,v.Vehicle_Type_Name }).ToList();
DriverVm.driver = db.drivers.Find(id);
foreach (var item in list)
{
DriverVm.VehicleList.Add(new Vehicle { Vehicle_Id = item.Vehicle_Id, Vehicle_Type_Name = item.Vehicle_Type_Name });
}
foreach (var item in DriverVm.driver.Vehicles)
{
DriverVm.SelectedVehicles.Add(item.Vehicle_Id);
}
return View(DriverVm);
}
And here is POST action for edit:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DriverViewModel driverVm)
{
var list = db.vehicles.Select(v =>
new { v.Vehicle_Id, v.Vehicle_Type_Name }).ToList();
foreach (var item in list)
{
driverVm.VehicleList.Add(
new Vehicle {
Vehicle_Id = item.Vehicle_Id,
Vehicle_Type_Name = item.Vehicle_Type_Name
});
}
if (ModelState.IsValid)
{
db.Entry(driverVm.driver).State = EntityState.Modified;
db.SaveChanges();
List<Vehicle> vhcls = new List<Vehicle>();
Driver driver = db.drivers.Find(driverVm.driver.driverId);
vhcls = driver.Vehicles.ToList();
foreach (Vehicle veh in vhcls)
{
driver.Vehicles.Remove(veh);
}
db.SaveChanges();
foreach (var item in driverVm.SelectedVehicles)
{
Vehicle vehicle = db.vehicles.Find(item);
driverVm.driver.Vehicles.Add(vehicle);
}
db.SaveChanges();
TempData["DriverSuccess"] = "1";
return RedirectToAction("Edit");
}
else
{
ViewBag.DriverError = "1";
}
return View(driverVm);
}
The actual problem is here :
Driver driver = db.drivers.Find(driverVm.driver.driverId);
vhcls = driver.Vehicles.ToList();
foreach (Vehicle veh in vhcls)
{
driver.Vehicles.Remove(veh);
}
db.SaveChanges()
The list "vhcls" in the above code is empty, it should contain the vehicles associated with drivers, but "driver" object contains Null collection in "driverVm.driver.Vehicles" instead of having associated vehicles, I am wandering badly but can't find the solution..Please help......
Just using find won't include related entities. It's very likely that driver contains the right entity, but that the Vehicles collection is empty.
Try using Include to make sure that the related entities will be included, and FirstOrDefault to emulate the result of Find.
Driver driver = db.drivers
.Include(d => d.Vehicles)
.FirstOrDefault(d => d.Id == driverVm.driver.driverId);
vhcls = driver.Vehicles.ToList();
Edit: I initially missed that you were already using Lazy Loading, so I adjusted the answer a bit.

How can I display a model property name that is coming from the database?

I currently am pulling a list of url's from a view using Entity Framework 5 and MVC 5. I have the view populating all the links but I need each link to display their 'LinkState' names like in my model so it will output:
Alabama
Georgia
etc.
with the link attached to the LinkState. Instead of the view foreach loop saying State Link. I cant get my model/controlled to pull the correct information.
Repository:
public class LinkRepository
{
private readonly LinkLibrary _entities = new LinkLibrary ();
public LinkRepository()
{
_entities = new LinkLibrary ();
}
public List<LinkModels> RetrieveStateLink(string year)
{
return
_entities.vw_URLLibrary.Where(s => s.YEAR.Equals(year) && s.URL_TYPE.Equals("United States")).Select(m => new LinkModels()
{
UrlLink = m.LinkLocation
}).ToList();
}
}
Model
public class LinkModels
{
public string LinkYear { get; set; }
public string LinkState { get; set; }
public string UrlLink { get; set; }
public string LinkType { get; set; }
public List<string> ListOfUrls{ get; set; }
}
Controller
public ActionResult GetStateLinks()
{
var stateLink = new List<string>();
var model = rr.RetrieveStateLinks("2014").Select(m=> m.UrlLink).ToList();
foreach (var s in model)
{
stateLink.Add(s);
}
var rm = new LinkModels();
rm.ListOfUrls = stateLink;
return View(rm);
}
View
#foreach (var item in Model.StateLinkList)
{
<td>
State Link
</td>
}
Your issue is that you are returning a List of strings as opposed to a list of LinkModels. I updated the repository to return the url and link name
removed some unneccessary code in your controller and updated it to work with a list of LinkObjects. Then updated the view to display the info.
You will have to update your view #model List<LinkModels> instead of #model List<string>
public class LinkRepository
{
private readonly LinkLibrary _entities = new LinkLibrary ();
public LinkRepository()
{
_entities = new LinkLibrary ();
}
public List<LinkModels> RetrieveStateLink(string year)
{
return
_entities.vw_URLLibrary.Where(s => s.YEAR.Equals(year) && s.URL_TYPE.Equals("United States")).Select(m => new LinkModels()
{
LinkState = m.LinkState,
UrlLink = m.LinkLocation
}).ToList();
}
}
public ActionResult GetStateLinks()
{
var stateLink = new List<LinkModels>();
var model = rr.RetrieveStateLinks("2014");
return View(model);
}
#foreach (var item in Model)
{
<td>
#item.LinkState
</td>
}
Controller
public ActionResult GetStateLinks()
{
var model = rr.RetrieveStateLinks("2014");
return View(model);
}
View (change your view model to list of LinkModels)
#foreach (var item in Model)
{
<td>
#item.LinkState
</td>
}

modelBinding works when using model but not with viewmodel

I'm trying to get a dropdown show the right value when editing using a viewmodel but it only works when i pass the complete model to the view.
When I do it like this and there is already a contact selected it shows that contact in the edit screen.
Model
public class ClientModel
{
public int ID { get; set; }
public int ContactID { get; set; }
//Other atributes
}
View EditContact
#model Project.Models.ClientModel
#Html.DropDownListFor(model => model.ContactID , (SelectList)ViewBag.ContactID, "select a contact")
Controller
public ActionResult EditContact(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var Contact = db.Contacts.ToList();
ViewBagID.Contact = new SelectList(Contact.AsEnumerable(), "ID", "name", "Contact");
ClientModel model= db.ClientModel.Find(id);
return View(model);
}
But when I do it like this and there is already a contact selected the dropdownlist shows select contact.
Model
public class ClientModel
{
public int ID { get; set; }
public int ContactID { get; set; }
//Other atributes
}
ViewModel
public class ClientEditContactModel
{
public int ID { get; set; }
public int ContactID { get; set; }
}
View EditContact
#model Project.Models.ClientEditContactModel
#Html.DropDownListFor(model => model.ContactID, (SelectList)ViewBag.ContactID, "select a contact")
Controller
public ActionResult EditContact(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var Contact = db.Contacts.ToList();
ViewBag.ContactID = new SelectList(Contact.AsEnumerable(), "ID", "name", "Contact");
ClientModel client= db.ClientModel.Find(id);
ClientEditContactModel model = new ClientEditContactModel();
model.ID = client.ID;
model.ContactID = client.ContactID
return View(model);
}
How do i fix this with the viewmodel?
Edit
I've made some typo's in my code so I fixed them but because of them i found the answer see below.
I found the answer after some more research here https://stackoverflow.com/a/11949123/4252392.
The problem was that ViewBag's name is the same as the model's property.
So i changed the Viewbag's name.
New Controller
public ActionResult EditContact(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var Contact = db.Contacts.ToList();
ViewBag.ContactIDList = new SelectList(Contact.AsEnumerable(), "ID",
"name", "Contact");
ClientModel client= db.ClientModel.Find(id);
ClientEditContactModel model = new ClientEditContactModel();
model.ID = client.ID;
model.ContactID = client.ContactID
return View(model);
}
New View
#model Project.Models.ClientEditContactModel
#Html.DropDownListFor(model => model.ContactID, (SelectList)ViewBag.ContactIDList,
"select a contact")
If you set selected value in ContactID property from dropdown so you need to set dropdown in view like below:
#model Project.Models.ClientEditContactModel
#Html.DropDownListFor(model => model.ContactID, (SelectList)ViewBag.Contact,
"select a contact")

How to display the ViewBag.products.Doc_Title and so on

I'm new to MVC5,I had troubles with the ViewBag
I want to display the ViewBag.products.Doc_Title,ViewBag.products.Doc_Content,ViewBag.products.Doc_Id and so on
but i don't know how to do it
it display what i don't want
can anybody help me?
Here is my controller
public class DocProductController : Controller
{
private IDocProductRepository repository;
private IDocMainRepository repositoryMain;
public DocProductController(IDocProductRepository docProductRepository, IDocMainRepository docMainRepository)
{
this.repository = docProductRepository;
this.repositoryMain = docMainRepository;
}
public ActionResult List()
{
var products = from docProduct in repository.DocProduct
join docMain in repositoryMain.DocMain
on docProduct.Doc_Id equals docMain.Doc_Id
select new { DocMainTitle = docMain.Doc_Title, DocProductContent = docProduct.DocProduct_Content };
ViewBag.products = products;
//DocProductListView model = new DocProductListView
//{
// DocProduct = repository.DocProduct
// .Join(repositoryMain.DocMain,
// docProduct => docProduct.Doc_Id,
// docMain => docMain.Doc_Id,
// (docProduct, docMain) => new { a = docMain.Doc_Id, b = docProduct.Doc_Id })
// .OrderByDescending(n => n.)
//};
return View();
}
}
//if my view is this
<div>
#foreach (dynamic p in ViewBag.products)
{
<div>
#*#p.Doc_Id*#
#p
</div>
}
</div>
//The page display:
{ DocMainTitle = name1, DocProductContent = content1 }
{ DocMainTitle = name2, DocProductContent = content2 }
//=====================================
//I want to display it like this
//#p.DocMainTitle #p.DocProductContent
//but it works error
<ul>
<li><h1>name1</h1>content1</li>
<li><h1>name2</h1>content2</li>
</ul>
Controller:
public class DocProductController : Controller
{
private IDocProductRepository repository;
private IDocMainRepository repositoryMain;
public DocProductController(IDocProductRepository docProductRepository,
IDocMainRepository docMainRepository)
{
this.repository = docProductRepository;
this.repositoryMain = docMainRepository;
}
public ActionResult DocProductList()
{
var model = new DocProductViewModel(repository);
//link tables(entities) part will be in the repository functions
//from docProduct in repository.DocProduct
//join docMain in repositoryMain.DocMain
//on docProduct.Doc_Id equals docMain.Doc_Id
//select new { DocMainTitle = docMain.Doc_Title,
//DocProductContent = docProduct.DocProduct_Content };
return View(model);
}
}
ViewModel:
public class DocProductViewModel
{
private IDocProductRepository repository;
public DocProductViewModel(IDocProductRepository docProductRepository)
{
this.repositoryMain = docMainRepository;
}
public IList<DocProduct> DocProductList
{
get
{
return repository.GetList();
}
}
}
Views in ~/views/DocProduct folder add view DocProductList.cshtml:
#model DocProductViewModel
<ul>
#foreach(var v in model.DocProductList)
{
<li><h1>#v.Doc_Title</h1>#v.Doc_Id</li>
}
</ul>
you can simply pass it to view like this:
return View(products);
and in your view define model of this type.
First you make a view model and strongly type you view with that model:
public class DocumentViewModel
{
public int Doc_Id {get;set;}
public string DocMainTitle { get; set;}
public string DocProductContent {get; set;}
}
In your action do like this:
public ActionResult List()
{
var products = (from docProduct in repository.DocProduct
join docMain in repositoryMain.DocMain
on docProduct.Doc_Id equals docMain.Doc_Id
select new DocumentViewModel { DocMainTitle = docMain.Doc_Title, DocProductContent = docProduct.DocProduct_Content }).ToList<DocumentViewModel>(;
ViewBag.products = products;
return View(products );
}
then in your view:
#model List<DocumentViewModel>
#foreach(var item in Model)
{
<h1>#item.DocMainTitle</h1>
<a>#item.Doc_Id</a>
}
UPDATE
IN your scenario, you want to pass multiple view models to a view, so you have to make another view model and create your two viewmodels as properties in it and pass this custom view model to view,
do like this:
public class CustomViewModel
{
public DocumentViewModel docViewModel {get;set;}
public SceondViewModel sceond {get;set;}
}
and in action:
var products = (from docProduct in repository.DocProduct
join docMain in repositoryMain.DocMain
on docProduct.Doc_Id equals docMain.Doc_Id
select new DocumentViewModel { DocMainTitle = docMain.Doc_Title, DocProductContent = docProduct.DocProduct_Content }).ToList<DocumentViewModel>();
CustomViewModel custom = new CustomViewModel();
custom.docViewModel =products ;
custom.sceond = secondviewmodel;
return View(custom);
In view, you model will be:
#model CustomViewModel
#
{
var firstViewModel = Model.docViewModel;
var secondViewModel = Model.sceond;
}

Trying to Convert my Model to IEnumerable<Model>

In my MedicalProductController I am trying to convert a MedicalProduct (model class) named "product" into IEnumerable<MedicalProduct> so it can be passed to GetMedicalProductViewModelList, which will return an IEnumerable<MedicalProductViewModel> (viewModel class).
I am trying to keep SQL calls to a minimum. as per advice of other stackoverflow members.
But "product" fails to turn into IEnumerable<MedicalProduct> in my MedicalProductController Class
MedicalProductController
public class MedicalProductController : Controller
{
private MvcMedicalStoreDb _db = new MvcMedicalStoreDb();
// other CRUD code omitted for brevity.
// =============
// Edit HttpGet
// =============
public ActionResult Edit(int id = 0)
{
MedicalProduct product = _db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
var productList = product as IEnumerable<MedicalProduct>;
var viewModelList = GetMedicalProductViewModelList(productList);
return View(viewModelList);
}
// =============
// Edit HttpPost
// =============
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(MedicalProduct product)
{
if (ModelState.IsValid)
{
_db.Entry(product).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
var productList = product as IEnumerable<MedicalProduct>;
var viewModel = GetMedicalProductViewModelList(productList);
return View(viewModel);
}
// =====================
// Mapper Class Helper
// =====================
public IEnumerable<MedicalProductViewModel> GetMedicalProductViewModelList(IEnumerable<MedicalProduct> productList)
{
var brandList = _db.Brands.ToArray();
var mapper = new MedicalProductMapper();
return mapper.MapMedicalProductViewModel(productList, brandList);
}
And just in case it is helpful, here is the mapping class:
MedicalProductMapper
public class MedicalProductMapper
{
// =====================
// Model to ViewModel
// =====================
public IEnumerable<MedicalProductViewModel> MapMedicalProductViewModel(IEnumerable<MedicalProduct> medicalProductList, IEnumerable<Brand> brandList)
{
var brandSelectListItem = brandList.Select(b => new SelectListItem()
{
Text = b.Name,
Value = b.Name
});
var viewModelList = medicalProductList.Select(p => new MedicalProductViewModel()
{
BrandID = p.BrandID,
BrandName = brandList.SingleOrDefault(b => b.ID == p.BrandID).Name,
BrandSelectListItem = brandSelectListItem,
ID = p.ID,
Price = p.Price,
Name = p.Name
});
return viewModelList;
}
// =====================
// ViewModel to Model
// =====================
public MedicalProduct MapMedicalProduct(MedicalProductViewModel VM)
{
var model = new MedicalProduct()
{
Name = VM.Name,
Price = VM.Price,
BrandID = VM.BrandID
};
return model;
}
}
Instead of
var productList = product as IEnumerable<MedicalProduct>;
Try
var productList = new List<MedicalProduct> { product };
You can't cast to IEnumerable<MedicalProduct> if it's not an IEnumerable, what I did in this example is first create a new List of type MedicalProduct and then add the product to the List.
List is one of the types that implement IEnumerable

Categories

Resources