Facing an issue regarding compiling my project - asp.net-mvc

Can anyone help me regarding the below issue I'm facing in the attached image. I'm trying to go to this url: http://localhost:49849/Customers but I couldn't. Thanks in advance... Just to let you know I;m following Mosh's Cource.
enter image description here
Here is the Model code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations; //this is a namespace
namespace Vidly2.Models
{
public class Customers
{
public int id { get; set; }
[Required] // we cal changing the conventions dataannotations
[StringLength(255)]
public string name { get; set; }
public bool IsSubscribedToNewsletter { get; set; }
public MembershipType MembershipType { get; set; } // we call it navigation property because it allows us to navigate to another type
public byte MembershipTypeId { get; set; } //Fk
}
}
here is the Controller code:
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Vidly2.Models;
namespace Vidly2.Controllers
{
public class CustomersController : Controller
{
public ViewResult Index()
{
var customers = GetCustomers();
return View(customers);
}
public ActionResult Details(int id)
{
var customer = GetCustomers().SingleOrDefault(c => c.id == id);
if (customer == null)
return HttpNotFound();
return View(customer);
}
private IEnumerable<Customers> GetCustomers()
{
return new List<Customers>
{
new Customers { id =1, name = "John Smith" },
new Customers { id =2, name = "Mary Williams" }
};
}
}
}
and here is the view code which has the mentioned error regarding compiling the project:
#using System.Web.Mvc.Html;
#model IEnumerable<Vidly2.Models.Customers>
#*
Note: I've set the model for this view to IEnumerable<Customer>.
This is a simple interface implemented by the list class. Since
in this view we only want to iterate over this list, and we don't
need any of the operations in the List class (eg Add, Remove, etc),
it's better to use the IEnumerable interface, which allows use to
iterate over the list. If in the future, we replace the List with a
different data structure, as long as it is enumerable, our view code
will remain unchanged.
*#
#{
ViewBag.Title = "Customers";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Customers</h2>
#if (!Model.Any())
{
<p>We don't have any customers yet.</p>
}
else
{
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Customer</th>
</tr>
</thead>
<tbody>
#foreach (var customer in Model)
{
<tr>
<td>#Html.ActionLink(customer.Name, "Details", "Customers", new { id = customer.id }, null)</td>
</tr>
}
</tbody>
</table>
}

You have property mismatch for name, Like in your model it is in small case name, but in view you are using customer.Name which should be customer.name
#Html.ActionLink(customer.name, "Details", ...

Related

Dropdown list population from ViewModel

First of all, I know this question has been asked many, many times. I've read countless articles and Stack Overflow answers. I've tried to figure this problem out for four days and I think I need help if someone doesn't mind.
I have two databases. The employee database has a field called "DisplayName" -- the second database has a relationship with the first and they work together great. I'm able to call the two databases perfectly in another application.
You can see the in the picture Index Page
that I have a list of people. I want a dropdown below it that lists all display names in the database so employees can add themselves to the list. You'll see a dropdown in the image but it's not populated.
Seems simple. But geez. Part of a problem I'm having is my home controller already has a function to populate the list in the picture so I can't do another on that page. I've tried a lot of suggestions on a lot of sites. I get IEnumerable errors or display reference errors....
Here's my controller (again - it has nothing in it that helps the dropdown):
namespace SeatingChart.Controllers
{
public class HomeController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Employee
public ActionResult Index()
{
var lists = db.BreakModels
.Include("Employee")
.Include("TimeEntered")
.Include("TimeCleared")
.Include("DisplayName")
.Select(a => new HomeIndexViewModels
{
Employee = a.Employee,
DisplayName = a.EmployeeModels.DisplayName,
TimeEntered = a.TimeEntered,
TimeCleared = a.TimeCleared.Value,
Id = a.EmployeeModels.Id,
});
return View(lists);
}
View:
#model IEnumerable<SeatingChart.Models.HomeIndexViewModels>
#{
Layout = null;
}
#Html.Partial("_Header")
<div class="container_lists">
<div class="container_break col-md-8">
<h5 style="text-align:center">Break List</h5>
<table class="table-bordered col-lg-12">
#if (Model != null)
{
foreach (var item in Model)
{
if (item.TimeCleared == null)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.DisplayName)
</td>
<td>
 BV
</td>
<td>
 #item.TimeEntered.ToString("HH:mm")
</td>
</tr>
}
}
}
</table>
#using (Html.BeginForm())
{
<div class="row site-spaced">
<div class="col-3">
#Html.DropDownList("DisplayName", new SelectList(new List<string>() { "---Dispatcher---" }), new { #class = "required " })
</div>
</div>
<div class="col-3">
<input type="submit" value="Submit" class="site-control" />
</div>
}
</div>
</div>
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace SeatingChart.Models
{
public class HomeIndexViewModels
{
//Break Model
public int BreakId { get; set; }
public int Employee { get; set; }
public DateTime TimeEntered { get; set; }
public DateTime? TimeCleared { get; set; }
//Employee Model
public int Id { get; set; }
public string DisplayName { get; set; }
public string DisplayNames { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool NotActive { get; set; }
public int Force { get; set; }
public string EmployeeList { get; set; }
}
}
I hope this is clear enough. I've tried so many different ways with so much code - the errors are different with everything I've tried.
Thanks in advance for your patience and help!
You can add to your viewmodel
public List<SelectListItem> Employees { get; set; }
Then you can populate this list with controller then in view just call it with:
#Html.DropDownListFor(m => m.Id, Model.Employees, new { #class = "form-control", required = "required" })
Update - how to populate list. Should work (but not tested code).
public List<SelectListItem> GetEmployeeForDropdown(List<HomeIndexViewModels> list)
{
List<SelectListItem> empList = new List<SelectListItem>();
try
{
if (list != null && list.Count > 0)
{
foreach (var item in list)
{
empList.Add(new SelectListItem { Text = item.DisplayName, Value = item.Id.ToString() });
}
}
else
{
empList.Add(new SelectListItem { Text = "No items", Value = string.Empty });
}
}
catch (Exception ex)
{
//handle exceptions here
}
return empList;
}
Edit: Remember to use your model in view!

How to post view model to controller

I am trying to create a view that takes a view model, simply has an int property and a list of child model, with int; string; string properties.
What i am trying to do is everytime user clicks an "add line" button, i am creating a new child model in my view model list, letting user edit the properties and then want to post back to my controller but no matter what, it is always empty.
I know this must be simple but has me stumped for hours today? Is there some magic that needs to happen?
Any help appreciated.
My Controller:
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class EmployeeUploadController : Controller
{
// GET: EmployeeUpload
public ActionResult EmployeeUpload()
{
var vm = new EmployeeBulkUpload { UploadedBy = 12345 };
vm.Employees.Add(new EmployeeBulkUploadItem { Id = 1, JobTitle = "Labourer", Name = "Jimmy" });
return View(vm);
}
[HttpPost]
[ActionName("EmployeeUpload")]
public ActionResult EmployeeUploadPost(EmployeeBulkUpload vm)
{
return View(vm);
}
}
}
My Model:
using System.Collections.Generic;
namespace WebApplication1.Models
{
public class EmployeeBulkUpload
{
public EmployeeBulkUpload()
{
Employees = new List<EmployeeBulkUploadItem>();
}
public int UploadedBy { get; set; }
public List<EmployeeBulkUploadItem> Employees { get; set; }
}
public class EmployeeBulkUploadItem
{
public int Id { get; set; }
public string Name { get; set; }
public string JobTitle { get; set; }
}
}
My "Container" view:
#using WebApplication1.Models
#model WebApplication1.Models.EmployeeBulkUpload
#{
ViewBag.Title = "EmployeeUpload";
}<div>
#using (Html.BeginForm("EmployeeUpload", "EmployeeUpload", FormMethod.Post))
{
<h2>EmployeeUpload</h2>
<button>Add New</button>
foreach(EmployeeBulkUploadItem emp in Model.Employees)
{
Html.RenderPartial("_EmployeeUploadItem", emp);
}
<input type="submit" name="SaveButton" value="Save" />
}
</div>
My Item Partial view:
#model WebApplication1.Models.EmployeeBulkUploadItem
<li>
#Html.LabelFor(x => x.Id)
#Html.EditorFor(x => x.Id)
#Html.LabelFor(x => x.Name)
#Html.EditorFor(x => x.Name)
#Html.LabelFor(x => x.JobTitle)
#Html.EditorFor(x => x.JobTitle)
</li>
I can load with one record and post straight back but is always empty in my Controller EmployeeUploadPost method?

ASP MVC Nested Models

I need a view that displays rows of header-detail info. For a trivial case I set up a Course-Student tiny database with 4 simple tables. The Courses and Students tables are linked with a Section table which also has a student grade in it. Also, the Student table is owned by a Student Type Table. There are helper classes to hold the list of "header" data for the course and a "detail" list for each student who takes that class.
namespace SchoolA.Models
{
public class CourseInfo2
{
public int CourseID { get; set; }
public int CourseNumber { get; set; }
public string CourseName { get; set; }
public IEnumerable<CourseSectionList> CourseStudentList { get; set; }
}
}
namespace SchoolA.Models
{
public class CourseSectionList
{
public string Student { get; set; }
public string Type { get; set; }
public string Grade { get; set; }
}
}
The controller is:
public ActionResult Courselisting()
{
List<CourseInfo2> courseInfo2 = new List<CourseInfo2>();
List<CourseSectionList> courseSectionList = new List<CourseSectionList>();
var Cquery = from c in db.Courses select c;
foreach (var item in Cquery)
{
Course course = db.Courses.Find(item.CourseID); // first find the selected course
// get the sections
foreach (var s in query) // go through each section
{
// get the section data
courseSectionList.Add(new CourseSectionList
{
Student = student.StudentName,
Type = studentType.StudentTypeName,
Grade = s.SectionStudentGrade
});
} // end of section loop
courseInfo2.Add(new CourseInfo2
{
CourseID = course.CourseID,
CourseNumber = course.CourseNumber,
CourseName = course.CourseName,
CourseStudentList = courseSectionList
});
} // end of Course loop
return View(courseInfo2); // Course List and Section list for each course
}
The View is:
#model SchoolA.Models.CourseInfo2
#* doesn't work either: model List<SchoolA.Models.CourseInfo2>*#
<div>
<table>
<tr><th>ID</th> <th>Number</th> <th>Course</th></tr>
#foreach (var CourseInfo2 in Model)
{
<tr>
<td>
#CourseInfo2.CourseID
</td>
<td>
#CourseInfo2.CourseNumber
</td>
<td>
#CourseInfo2.CourseName
</td>
<td>
<table class="table">
<tr><th>Student</th> <th>Type</th><th>Grade</th></tr>
#foreach (var s in Model.CourseStudentList)
{
<tr>
<td>
#s.Student
</td>
<td>
#s.Type
</td>
<td>
#s.Grade
</td>
</tr>
}
</table>
</td>
</tr>
}
</table>
</div>
The problem is that I get a variety of errors as I try to pass these two models to the view. In the code as shown above I get this error:
CS1579: foreach statement cannot operate on variables of type 'SchoolA.Models.CourseInfo2' because 'SchoolA.Models.CourseInfo2' does not contain a public definition for 'GetEnumerator'
I've tried a number of variations for passing the models but always run into one error other the other that prevents both models from working in the view. I should note that I tested each part of the view independently and the controller code works fine to deliver the correct data to the view. However, I can't combine the two.
The problem seems to be the way I create instances of the models an how they are passed to the view. What am I doing wrong?
You're passing your view a List<SchoolA.Models.CourseInfo2>, but the view expects a single SchoolA.Models.CourseInfo2.
Change your #model declaration to IEnumerable<SchoolA.Models.CourseInfo2>.
Then change your foreach loops.
Change the first loop to foreach (var courseInfo in Model)
Change the inner loop to foreach (var s in courseInfo.CourseStudentList)
You are passing a model which is list of object, while in view you have single object.
Change your view model bind as below:
#model List<SchoolA.Models.CourseInfo2>
Problem: I have to edit Level2Name (by UI it's a textbox inside the child grid).
I'm able to edit Level1name (parent grid text field) and able to get value in my controller.
Question: How do I able to edit the nested textbox.
What I've tried.
Code:
Model
public class Level0
{
public Level0()
{
Level1= new List<Level1>();
}
public int? ID{ get; set; }
public int? NameText{ get; set; }
public List<Level1> lev1{ get; set; }
}
public class Level1
{
public Level1()
{
Level2= new List<Level2>();
}
public int Lev1ID {get;set;}
public string Level1name{ get; set; }
public List<Level2> level2{ get; set; }
}
public class Level2
{
public string Level2_ID { get; set; }
public string Level2Name{ get; set; }
}
UI Code
#for (int i = 0; i < Model.Level1.Count; i++)
{
#Html.HiddenFor(modelItem => Model.Floors[i].Lev1ID )
#for (int j = 0; j < Model.Level1[i].Level2.Count; j++)
{
#Html.HiddenFor(m => m.Level1[i].Level2[j].OP)
#Html.TextBoxFor(m => m.Level1[i].Level2[j].Level2Name, new { #class = "form-control" })
}
}

Generate Razor view with multiple models in model class

So basically I have a model for all my recipes and I want to create a view that shows a list of all the recipes with a boolean if the current logged in user can edit the recipe. I've made a Presentation Model to do this. However, when I click 'Add View' in the controller and generate a new view with this presentation model, the view only shows the boolean, fields of 'recipe'. What should I do to generate a view with the bool and all fields of 'recipe'.
Model 'Recipe':
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ReceptenApp.Models
{
public class Recept
{
public int Id { get; set; }
public int Category { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Cook { get; set; }
}
}
Presentation Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ReceptenApp.Models.PresentationModels
{
public class PMReceptListItem
{
public PMReceptListItem()
{
recept = new ReceptWithCats();
}
public ReceptWithCats recept { get; set; }
public bool ShowEdit { get; set; }
}
}
View after generating it:
#model IEnumerable<ReceptenApp.Models.PresentationModels.PMReceptListItem>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ShowEdit)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ShowEdit)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
Since your view is listing all the Recept's, Let's update your presentation model(view model) to reflect that. We will also create a new viewmodel (ReceptViewModel) to represent the Recept entity. We will add ReceptList in the ReceptListViewModel which a List of our new ReceptViewModel so that we can pass a list of Recept's to the view.
public class ReceptViewModel
{
public int Id {set;get;}
public string Title {set;get;}
public string Description {set;get;}
public string Cook {set;get;}
}
public class ReceptListViewModel
{
public PMReceptListItem()
{
ReceptList = new List<ReceptViewModel>();
}
public List<ReceptViewModel> ReceptList { get; set; }
public bool ShowEdit { get; set; }
}
and in your GET action,read the data from your db and load to an object of our ReceptListViewModel
public ActionResult Index()
{
var vm= new ReceptListViewModel();
vm.ReceptList = db.Recepts.Select(x=>new ReceptViewModel {
Id=s.Id,
Title=x.Title,
Description=x.Description,
Cook=x.Cook }).ToList();
vm.ShowEdit = true ; //Set this value based on your condition
return View(vm);
}
and in your GET view
#model List<ReceptListViewModel>
<h2>List of Recepts</h2>
<table>
#foreach(var r in Model.ReceptList)
{
<tr>
<td>#r.Title</td>
<td>#r.Description</td>
<td>#r.Cook</td>
#if(Model.ShowEdit)
{
<td>#Html.ActionLink("Edit","Edit",new { id=r.Id})</td>
<td>#Html.ActionLink("Delete","Delete",new { id=r.Id})</td>
}
</tr>
}
</table>

How do I make a foreign key display only once in #foreach in MVC 5

I have a project (below) where I have Categories and Products. Each category will have multiple products and as you can see from the models, the Category ID is referenced as a Foreign Key. What I am trying to do is to have each Category display as a div with the corresponding products shown in a unordered list beneath. With the code I have, I keep ending up with a div and one product with categories repeating for each product.
I have searched and searched but can't seem to find the solution. Where I am I going wrong?
ViewModel
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace WebApplication1.Web.Models
{
public class Category
{
public int CategoryID { get; set; }
[Required, Display(Name = "Category Name")]
public string CategoryName { get; set; }
public bool IsDisplayedInMainMenu { get; set; }
}
public class Product
{
public int ProductID { get; set; }
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
[Display(Name = "Category Name")]
public Category CategoryName { get; set; }
[Required, Display(Name = "Product Name")]
public string ProductName { get; set; }
[Required, Display(Name = "Product Description")]
[DataType(DataType.MultilineText)]
public string ProductDescription { get; set; }
}
}
Products Controller
namespace WebApplication1.Controllers
{
public class ProductsController : Controller
{
private ServiceContext db = new ServiceContext();
// GET: Products
public ActionResult Index()
{
var products = db.Products.Include(p => p.CategoryName);
return View(products.ToList());
}
}
}
View
model IEnumerable
#{
ViewBag.Title = "Products";
}
<h2>#ViewBag.Title</h2>
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-3">
<h4><strong>#item.CategoryName.CategoryName</strong></h4>
<ul class="list-unstyled">
#if (item.ProductName.Any())
{
<li>
#item.ProductName
</li>
}
</ul>
</div>
}
</div>
Products
Lumber
2 X 4
Lumber
1 X 4
Lumber
Plywood
Power Tools
Drill
Power Tools
Circular Saw
Garden
Lemon Tree
Garden
Orange Tree
Fasteners
Drywall screws
Fasteners
Deck Screws
Change the data you're sending to the view. Instead of this.DB.Products...try the following:
return this.View(this.DB.Category.Select(x => new { CategoryName = x.CategoryName, Products = x.Products);
...or something similar depending on your database structure. The idea is to have a model that resembles what you actually want to display in the view. This is commonly referred to as a view model.
public class CategoryViewModel
{
public string CategoryName {get; set;}
public IEnumerable<Product> Products {get; set;}
}
If you had such a class, then your controller method might look like this:
return this.View(this.DB.Category.Select(x => new CategoryViewModel { CategoryName = x.CategoryName, Products = x.Products));
Then in your view:
<div class="col-md-3">
<h4><strong>#Model.CategoryName</strong></h4>
#foreach (var item in Model.Products)
{
<ul class="list-unstyled">
#item.ProductName (or something)
</ul>
}
</div>
I'm not on a dev machine so I can't really tell if I've made typos. I'm happy to answer any questions you might have though.
If you are returning products under a selected category, you can use below code
#if(Model.Count()>0)
{
<h4><strong>#Model.ToList()[0].CategoryName.CategoryName</strong></h4>
}
Hope it will works

Resources