Model:
public class Service
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
ViewModel:
public class FullPrice
{
public IEnumerable<Service> Services { get; set; }
}
View:
#model hotel.Models.FullPrice
#foreach(Service service in Model.Services)
{
//
}
My view model is NULL. Why?
Model would be NULL because there is no currently existing instance as the view is being executed.
Usually, the way to pass a model instance into a view would be in the corresponding action method like
public View myActionMethod()
{
hotel.Models.FullPrice model = new hotel.Models.FullPrice();
model.Services = new List<Service>();//Also prevent NULL exception with this property
return View(model);
}
I guess it's not the model what is null, but the Services. Change the action code to
FullPrice model = new FullPrice
{
Services = new List<Service>()
};
return View(model);
Change your ViewModel code to below
public class FullPrice
{
public FullPrice()
{
this.Services = new List<Service>();
}
public IEnumerable<Service> Services { get; set; }
}
so the Services property won't be null when you do this
FullPrice model = new FullPrice();
Related
I am looking for selecting a list from my table based on another table. I need to retrieve system names that are part of a particular system family. i have already added foreign keys. I created a ViewModel containing both these classes but it throws a null pointer exception. I am new to MVC and I am not sure where I am wrong.
Model Class : Systems
public class Systems
{
public int SystemsID { get; set; }
public string SystemName { get; set; }
public DateTime CreatedOn { get; set;}
public string CreatedBy { get; set; }
public int SystemFamilyID { get; set; }
public virtual SystemFamily SystemFamily { get; set; }
}
Class SystemFamily
public class SystemFamily
{
public int SystemFamilyID { get; set;}
public int SystemsID {get;set;}
public string FamilyName { get; set; }
public DateTime DateCreated { get; set; }
public string CreatedBy { get; set; }
public virtual ICollection<Systems> Systems { get; set; }
}
ViewSystem is a method in my SystemFamilyController.
public ActionResult ViewSystem(int? id)
{
var viewmodel = new Sys_SysFam();
ViewBag.SystemFamilyID = id.Value;
//if (id != null)
//{
// ViewBag.SystemFamilyID = id.Value;
// viewmodel.Systems = viewmodel.SystemFamily.Where(
// i => i.SystemFamilyID == id.Value).Single().Systems;
//}
return View(viewmodel);
}
the view :
#model SystemFam_System.ViewModel.Sys_SysFam
#{
ViewBag.Title = "ViewSystem";
}
<h2>ViewSystem</h2>
<p>#ViewBag.SystemFamilyID</p>
<table>
#foreach (var item in Model.Systems)
{
string selectedRow = "";
if (item.SystemFamilyID == ViewBag.SystemFamilyID)
{
//{
// selectedRow = "success";
//}
<tr class="#selectedRow">
<td>
#item.SystemName
</td>
<td>
#item.SystemsID
</td>
<td>
#item.SystemFamily
</td>
</tr>
}
}
</table>
I get null pointer Exception. I want to view the system that belongs to a particular family in view system.
Thanks in advance!!
Vini
Edit :
public class Sys_SysFam
{
public IEnumerable<Systems> Systems { get; set; }
public SystemFamily SystemFamily { get; set; }
}
Ok i have checked Sys_SysFam class too. As per your current code it will always throw null reference exception becasue in your controller code you are using:
public ActionResult ViewSystem(int? id)
{
var viewmodel = new Sys_SysFam();
ViewBag.SystemFamilyID = id.Value;
//if (id != null)
//{
// ViewBag.SystemFamilyID = id.Value;
// viewmodel.Systems = viewmodel.SystemFamily.Where(
// i => i.SystemFamilyID == id.Value).Single().Systems;
//}
return View(viewmodel);
}
here you are creating an object of Sys_SysFam as viewmodel and as your if part is commented so you are returning same viewmodel in which viewmodel.Systems will always be null. Here i did not see any request to database for getting the data from db but i think your data in viewmodel will come from database and if i uncomment your if condition then too you are not sending any request to database you are using same viewmodel object created above.
viewmodel.Systems = viewmodel.SystemFamily.Where(
i => i.SystemFamilyID == id.Value).Single().Systems;
in right side you are using viewmodel.SystemFamily with where condition but as viewmodel.SystemFamily is null it will always throw exception. Your solution should be something like this:
public ActionResult ViewSystem(int? id)
{
DataContext context = new DataContext();
var viewmodel = new Sys_SysFam();
ViewBag.SystemFamilyID = id.Value;
if (id != null)
{
ViewBag.SystemFamilyID = id.Value;
var sysFamily = context.SystemFamily.Include(x => x.Systems).FirstOrDefault(x => x.SystemFamilyID == id.Value);
if (sysFamily != null)
{
viewmodel.Systems = sysFamily.Systems;
}
}
return View(viewmodel);
}
here first i am creating object of DataContext which is my main context to access the database using entity framework. so first i will get the system family based on passed id from database and if system family is not null then i will set the data of systems in viewmodel. Include method will bring data for Systems based on system family from database.
Also improve your Sys_SysFam class to initialize systems so that it will not throw exception in your view when there is no data in viewmodel.Systems like this:
public class Sys_SysFam
{
public Sys_SysFam()
{
this.Systems = new List<Systems>();
}
public SystemFamily SystemFamily { get; set; }
public IEnumerable<Systems> Systems { get; set; }
}
Hope this will help you.
Remove SystemsID property from SystemFamily class because it is not used for ICollection virtual property. so your SystemFamily class should be like this:
public class SystemFamily
{
public int SystemFamilyID { get; set;}
public string FamilyName { get; set; }
public DateTime DateCreated { get; set; }
public string CreatedBy { get; set; }
public virtual ICollection<Systems> Systems { get; set; }
}
A friend of mine could find me a way. But it doesnt use any ViewModel. I would like to know how it need to be done with ViewModel as well..
public ActionResult ViewSystem(int? id)
{
var model = from item in db.Systems
orderby item.SystemsID
where item.SystemFamilyID == id
select item;
return View(model);
}
I am creating mvc4 applicationn using entity framework 5
i am creating a page this contains checkboxes
i created table in db
model class
public class EmpSkillSet
{
public int ID { get; set; }
public string Skill { get; set; }
public bool isSelected { get; set; }
}
}
controller
[HttpPost]
public string AddSkills(IEnumerable<EmpSkillSet> skills)
{
}
How do I create a checkbox in the view?
Then how do i get its value from the database?
By using this example you can fetch only boolen value (True or False)
In view:
#Html.CheckBox("MonOpen", l.MonOpen)
In MOdel:
public class Shop
{
public bool MonOpen { get; set; }
....
}
in controller:
[HttpPost]
public ActionResult ShopCreate(Shop location)
{
Location newShop = new Location();
newShop.MonOpen = location.MonOpen;
....
}
I am trying to include a list of Clients in a drop down box. I am including this list in a form (the Html.BeginForm()) so that I can pass the selected value to my POST controller. I think I am missing something, I have the following classes:
my Invoice ViewModel:
public class InvoiceViewModel
{
public InvoiceViewModel()
{
// makes sure InvoiceItems is not null after construction
InvoiceItems = new List<PrelimInvoice>();
}
public List<PrelimInvoice> InvoiceItems { get; set; }
public List<Client> ClientId { get; set; }
public Client Client { get; set; }
public decimal InvoiceTotal { get; set; }
}
My Client Model:
public class Client
{
public string ClientId { get; set; }
public string Name { get; set; }
}
My SaveInvoice method:
public ActionResult SaveInvoice()
{
var invoice = new Invoice();
TryUpdateModel(invoice);
try
{
invoice.ClientId = User.Identity.Name;
invoice.DateCreated = DateTime.Now;
//Save invoice
proent.Invoices.Add(invoice);
proent.SaveChanges();
//Process the invoice
var preliminvoice = InvoiceLogic.GetInvoice(this.HttpContext);
preliminvoice.CreateInvoice(invoice);
return RedirectToAction("Complete", new { id = invoice.InvoiceId });
}
catch
{
//Invalid - redisplay with errors
return View(invoice);
}
}
And my Index.cshtml is strongly typed to the InvoiceViewModel class.
Index.cshtml is where I generate the form.
I am not sure of the code for creating the Html.DropDownList, and whether or not I need to include a List or something of my Clients. I have dropdownlists in other places but they are strongly typed to models, not viewmodels, hence my confusion.
Can anyone assist me?
Start by adding to your ViewModel the following 2 properties:
SelectedClientId: which stores the selected value
ClientItems: stores the collection of SelectListItems which populates your drop down.
E.G.
public class ClientViewModel
{
public List<Client> Clients;
public int SelectedClientId { get; set; } // from point 1 above
public IEnumerable<SelectListItem> ClientItems // point 2 above
{
get { return new SelectList(Clients, "Id", "Name");}
}
}
Then on your View index.cshtml you would add the following:
#model ClientViewModel
#Html.DropDownListFor(m => m.SelectedClientId, Model.ClientItems)
I get the following error in the DropDownListFor() "An expression tree may not contain a dynamic operation" because the lambda uses a dynamic type.
How can I set the selected option on the DropDownList without resorting to jQuery?
I would also rather not make a template or custom helper.
Model
public class Thing : Base {
public virtual Nullable<int> OptionID { get; set; }
public virtual Option Option { get; set; }
}
public class Option : Base {
public virtual ICollection<Thing> Things { get; set; }
}
public class Base {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
Controller
public ActionResult Edit(int Id) {
return View(new ViewModel(context, new Thing()));
}
View
#model MvcApp7.Models.ViewModel
#{
var Entity = (dynamic)Model.Entity;
}
#Html.DropDownListFor(x => Entity.OptionID , (System.Web.Mvc.SelectList)Model.Options)
ViewModel
public class ViewModel {
public ViewModel(Context context, object entity) {
this.Entity = entity;
this.Options = new SelectList(context.Options, "Id", "Name");
}
public dynamic Entity { get; set; }
public SelectList Options { get; set; }
}
EDIT: Please excuse me. I forgot that I could specify the selected option in the SelectList itself. I moved the responsibility into the ViewModel and will try to deal with it from there. However, it would still be good to know how to work around this in the View itself in case it was necessary.
I did this in the ViewModel
this.Options = new SelectList(context.Options, "Id", "Name", this.Entity.OptionID);
and this in the View
#Html.DropDownList("OptionID", Model.Options)
View
#model MvcApp7.Models.ViewModel
#Html.DropDownListFor(x => x.Entity.OptionID , (System.Web.Mvc.SelectList)Model.Options)
ViewModel
public class ViewModel {
public ViewModel(Context context, object entity) {
this.Entity = entity;
this.Options = new SelectList(context.Options, "Id", "Name");
}
public dynamic Entity { get; set; }
public SelectList Options { get; set; }
}
Every time I add a new App It creates a new AppCategory. I am seriously screwing this up somehow
code first entity framework objects
public class AppCategory
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<App> apps { get; set; }
}
public class App
{
public int ID { get; set; }
public string Name { get; set; }
public AppCategory Category { get; set; }
}
Editor Template (I would love to just make just one Foreign Key EditorTemplate)
#inherits System.Web.Mvc.WebViewPage
#Html.DropDownList("Category", LIG2010RedesignMVC3.Models.Repo.GetAppCategoriesSelect())
and of course the repository
public static IEnumerable<SelectListItem> GetAppCategoriesSelect()
{
return (from p in GetAppCategories()
select new SelectListItem
{
Text = p.Name,
Value = p.ID.ToString(),
});
}
public static ICollection<AppCategory> GetAppCategories()
{
var context = new LIGDataContext();
return context.AppCategories.ToList();
}
Every time I add a new App It creates a new AppCategory I am seriously screwing this up somehow
Adding more debug info
#inherits System.Web.Mvc.WebViewPage
#Html.DropDownList("", LIG2010RedesignMVC3.Models.Repo.GetAppCategoriesSelect())
gives me a validation message on the post
Parameters application/x-www-form-urlencoded
Category 1
Name 8
Validation error The value '1' is invalid.
This makes sense because Category should be an object not an integer.
Controller Code as asked for
pretty sure this isnt the problem as it came from MVCScaffold
[HttpPost]
public ActionResult Create(App d)
{
if (ModelState.IsValid)
{
context.Apps.Add(d);
context.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
My model was incorrectly set up ... virtual ICollection and just the foreign key id for the sub and everything worked... changes below
Model
public class AppCategory
{
public int ID { get; set; }
public string Name { get; set; }
public **virtual** ICollection<App> Apps { get; set; }
}
public class App
{
public int ID { get; set; }
********************************************
[UIHint("AppCategory")]
public int AppCategoryID { get; set; }
********************************************
public string Name { get; set; }
}
public class LIGDataContext : DbContext
{
public DbSet<AppCategory> AppCategories { get; set; }
public DbSet<App> Apps { get; set; }
}
/Views/Shared/EditorTemplates/AppCategory.cshtml
#inherits System.Web.Mvc.WebViewPage
#Html.DropDownList("", LIG2010RedesignMVC3.Models.Repo.GetAppCategoriesSelect())
AppController
[HttpPost]
public ActionResult Create(App d)
{
if (ModelState.IsValid)
{
this.repository.Add(d);
this.repository.Save();
return RedirectToAction("Index");
}
return View();
}
If you bind your dropDownList to Category.Id, you'll at least get the selected value into that filed, but nothing else in your Category Object.
The model binder cannot create the AppCategory object from the form collection in your Create action because the form only has an ID for that object (the other properties of AppCategory are not there).
The quickest solution would be setting the Category property of your App object manually, like this :
[HttpPost]
public ActionResult Create(App d) {
int categoryId = 0;
if (!int.TryParse(Request.Form["Category"] ?? String.Empty, out categoryId) {
// the posted category ID is not valid
ModelState.AddModelError("Category",
"Please select a valid app category.")
} else {
// I'm assuming there's a method to get an AppCategory by ID.
AppCategory c = context.GetAppCategory(categoryID);
if (c == null) {
// couldn't find the AppCategory with the given ID.
ModelState.AddModelError("Category",
"The selected app category does not exist.")
} else {
// set the category of the new App.
d.Category = c;
}
}
if (ModelState.IsValid)
{
context.Apps.Add(d);
context.SaveChanges();
return RedirectToAction("Index");
}
return View();
}