Mvc Drop Down List With Repository - c#

I am trying to get the id selected from a dropdown so that i can set it against my business logic method. I am using a repository pattern and my code is as follows.
However when i run the program, I get an error The insert statement conflicted with the foreign key.
Database Table
public class Item
{
[Key]
public int ItemId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string ItemArtUrl { get; set; }
public int CategoryId { get; set; }
[ForeignKey("CategoryId")]
public virtual Category Categories { get; set; }
}
Database table
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual IEnumerable<Item> Items { get; set; }
}
ViewModel
public class ItemViewModel
{
[Key]
public int ItemId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string ItemArtUrl { get; set; }
public int CategoryId { get; set; }
[ForeignKey("CategoryId")]
public IEnumerable<SelectListItem> CategoriesSelectListItem { get; set;}
}
ViewModel
public class CategoryViewModel
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Business Logic Layer
public class ItemBusiness : IItemBusiness
{
public void Insert(ItemViewModel item)
{
var itemrepo = new ItemRepository();
Item i = new Item();
i.Title = item.Title;
i.Price = item.Price;
i.ItemArtUrl = item.ItemArtUrl;
i.CategoryId = item.CategoryId;
itemrepo.Insert(i);
}
public List<ItemViewModel> GetAllItems()
{
var itemrepo = new ItemRepository();
var query = (from x in itemrepo.GetAll()
select new ItemViewModel()
{
Title = x.Title,
Price = x.Price,
ItemArtUrl = x.ItemArtUrl,
CategoryId = x.CategoryId
}).ToList();
return query;
}
}
Controller
[HttpGet]
public ActionResult Create()
{
var categoryBusiness = new CategoryBusiness();
ViewBag.items = new SelectList(categoryBusiness.GetAllCategories(), "CategoryId", "Name");
return View();
}
[HttpPost]
public ActionResult Create(ItemViewModel item)
{
var itemBusiness = new ItemBusiness();
itemBusiness.Insert(item);
return View();
}
public ActionResult Index()
{
var itemBusiness = new ItemBusiness();
return View(itemBusiness.GetAllItems());
}
}

I am assuming your Create view is set up to use ItemViewModel since you are returning it in the [HTTPPost] So instead of using ViewBag.Items = dropdownlist, set your ItemViewModel.CategoriesSelectListItem to that list.
You would have to change your Controller to send an 'empty' ItemViewModel except with the CategoriesSelectionListItem
public ActionResult Create()
{
ItemViewModel ivm = new ItemViewModel();
var categoryBusiness = new CategoryBusiness();
ivm.CategoriesSelectionListItem = new SelectList(categoryBusiness.GetAllCategories(), "CategoryId", "Name");
return View(ivm);
}
Then in your view set up the dropdownlist like this and it will return the CategoryId as part of the Model
#Html.DropDownList("CategoryId", Model.CategoriesSelectListItem, htmlAttributes: new { #class = "form-control" })

Related

Mvc.WebViewPage<T>.Model.get returned null and Id in Create view

I'm getting this error while trying to create object while using DropDown and ListBox lists
System.NullReferenceException System.Web.Mvc.WebViewPage.Model.get returned null.
Model
public class Game
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public Publisher Publishers { get; set; }
public int PublisherID { get; set; }
public List<Category> Categories { get; set; }
public string ImageLink { get; set; }
public Game()
{
Categories = new List<Category>();
}
}
View Model
public class GameViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public object Category { get; set; }
public Publisher Publisher { get; set; }
public string ImageLink { get; set; }
public GameViewModel(int id, string title, List<Category> category, Publisher publisher, string imageLink)
{
this.ID = id;
this.Title = title;
this.Category = category;
this.Publisher = publisher;
this.ImageLink = imageLink;
}
Create View Model
public class CreateGameViewModel{
public Game Game { get; private set; }
public List<SelectListItem> Categories { get; private set; }
public List<SelectListItem> Publishers { get; private set; }
public int[] SelectedCategory { get; set; }
public CreateGameViewModel()
{
this.Game = new Game();
}
public CreateGameViewModel(List<Models.Category> categories, List<Models.Publisher> publishers)
{
Categories = categories.Select(c => new SelectListItem() { Text = c.Name, Value = c.Id.ToString() }).ToList();
Publishers = publishers.Select(p => new SelectListItem() { Text = p.Name, Value = p.Id.ToString() }).ToList();
}
}
My controller
GET
public ActionResult Create()
{
var publishers = _db.Publishers.ToList();
var categories = _db.Categories.ToList();
var gameVM = new CreateGameViewModel(categories: categories, publishers: publishers);
return View(gameVM);
}
POST
[HttpPost]
public ActionResult Create(CreateGameViewModel game)
{
try
{
var categories = _db.Categories.Where(c => game.SelectedCategory.Contains(c.Id)).ToList();
game.Game.Categories = categories;
_db.Games.Add(game.Game);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
My view(where error shows up)
#Html.DropDownListFor(m => m.Game.PublisherID, Model.Publishers)
#Html.ListBoxFor(m => m.SelectedCategory, Model.Categories)
I'm also having editor for id and PublisherID in this create view which surely isn't right, but I'm not sure where to pinpoint that issue, while the other one exist.
Could someone take a look at this code?
So i think your problem is Game is not defined, so when you try and do #Html.DropDownListFor(m => m.Game.PublisherID, Model.Publishers) it's game being null that gives your error
Your code:
public class CreateGameViewModel
{
public Game Game { get; private set; }
public List<SelectListItem> Categories { get; private set; }
public List<SelectListItem> Publishers { get; private set; }
public int[] SelectedCategory { get; set; }
public CreateGameViewModel()
{
this.Game = new Game();
}
public CreateGameViewModel(List<Models.Category> categories,
List<Models.Publisher> publishers)
{
Categories = categories.Select(c => new SelectListItem() { Text = c.Name,
Value = c.Id.ToString() }).ToList();
Publishers = publishers.Select(p => new SelectListItem() { Text = p.Name,
Value = p.Id.ToString() }).ToList();
}
}
Fix:
public class CreateGameViewModel
{
public Game Game { get; private set; }
public List<SelectListItem> Categories { get; private set; }
public List<SelectListItem> Publishers { get; private set; }
public int[] SelectedCategory { get; set; }
public CreateGameViewModel()
{
this.Game = new Game();
}
public CreateGameViewModel(List<Models.Category> categories,
List<Models.Publisher> publishers)
:this()
{
Categories = categories.Select(c => new SelectListItem() { Text = c.Name,
Value = c.Id.ToString() }).ToList();
Publishers = publishers.Select(p => new SelectListItem() { Text = p.Name,
Value = p.Id.ToString() }).ToList();
}
}
The minor difference being the :this() at the second constructor, this should call the first constructor initialising Game which should stop the error from happening
Hope this helps

Get the less-sold items with LINQ

I have 2 objects (Order and Product) and a third (OrderDetail) that will be used as "navigation" between Products and Orders.
I'm trying to build a view that will show the less-sold products. For that I am "querying" the object OrderDetail and saving the result in a view model to later on be used in the view.
Model:
public class Product
{
public int ProductID { get; set; }
public string CodProduct { get; set; }
public string Nome { get; set; }
(...)
public ICollection<OrderDetail> OrderDetails { get; set; }
}
public class Order
{
public int OrderID { get; set; }
(...)
[BindNever]
public ICollection<OrderDetail> OrderDetails { get; set; }
}
public class OrderDetail
{
public int OrderDetailId { get; set; }
public int OrderId { get; set; }
public int ProductID { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public virtual Product Product { get; set; }
public virtual Order Order { get; set; }
}
ViewModel:
public class ProductSoldViewModel
{
//Data from the Product
public string ProductCode { get; set; }
public string ProductName { get; set; }
//Data from the OrderDetail
public int Qty { get; set; }
}
Controller:
public IActionResult LSProducts()
{
List<ProductSoldViewModel> model = new List<ProductSoldViewModel>();
model = _context.OrderDetail
.GroupBy(od => od.ProductID)
.Select(o => new ProductSoldViewModel
{
ProductCode = o.Select(s => s.Product.CodProduct).FirstOrDefault(),
ProductName = o.Select(s => s.Product.Nome).FirstOrDefault(),
Qty = o.Sum(s => s.Quantity)
})
.OrderBy(od => od.Qty)
.ToList();
return View(model);
}
With this code, I get only the less-sold products that are present in the orders. But I need to get all the products, even those that have never been sold.
Can you give me some advice about how can I do that?
You should query the product table if you need to get all products:
public IActionResult LSProducts()
{
List<ProductSoldViewModel> model = new List<ProductSoldViewModel>();
model = _context.Product
.Include(a => a.OrderDetails)
.Select(o => new ProductSoldViewModel
{
ProductCode = o.CodProduct,
ProductName = o.Nome,
Qty = o.OrderDetails.Sum(s => s.Qty)
})
.OrderBy(od => od.Qty)
.ToList();
return View(model);
}
To avoid a null exception you may want to add the following constructor to your model:
public class Product
{
public Product()
{
OrderDetails = new HashSet<OrderDetail>();
}
(...)
public ICollection<OrderDetail> OrderDetails { get; set; }
}

MVC Insert row into database with dropdown from another model

I am trying to create a "Create" form to insert new Results into a table. I have one model which is mapped to this table, first of the three shown below, and another two that I want to use to display data for dropdowns, but bind the result to APLayerID, BPlayerID and CourseID.
In other words, I want a list of A PlayerNames, B PlayersNames and Courses which map to the APLayerID, BPlayerID and COurseID within EditSingles.
I have tried creating a ViewModel, also below, which contains all three of these models, and passing that to the View but i'm really not sure what i'm doing!
In my controller I have a _model.SaveResults(EditSingles) which works well if i'm simply using EditSingles in the View, however I want to display the names of the players and Course so it's easier for adding rows, rather than having to remember the ID numbers.
public class EditSingles
{
[Key]
public int GameID { get; set; }
public int APlayerID { get; set; }
public int BPlayerID { get; set; }
public int Score { get; set; }
public int Winner { get; set; }
public int GYear { get; set; }
public int CourseID { get; set; }
}
Golfer:
public class Golfer
{
[Key]
public int PlayerID { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public string ImageURL { get; set; }
}
Course
public class Courses
{
[Key]
public int CourseID { get; set; }
public string CourseName { get; set; }
public int CoursePar { get; set; }
public string CourseAddress { get; set; }
[DataType(DataType.Date)]
public DateTime DatePlayed { get; set; }
public string CourseInformation { get; set; }
}
ViewModel
public class AdminModel
{
public IEnumerable<EditSingles> EditSingleResults { get; set; }
public IEnumerable<GolferDetails> GolferDetails { get; set; }
public IEnumerable<Courses> CourseDetails { get; set; }
}
You need a view model that contains the relevant properties of EditSingles plus properties for the collections of Golfers and Courses
public class EditSinglesVM
{
[Required(ErrorMessage = "Please select player A")]
[Display(Name = "Player A")]
public int APlayerID { get; set; }
....
[Required(ErrorMessage = "Please select a course")]
[Display(Name = "Course")]
public int CourseID { get; set; }
public IEnumerable<SelectListItem> PlayerList { get; set; }
public IEnumerable<SelectListItem> CourseList { get; set }
}
Then in the GET method (assumes you creating a new record)
public ActionResult EditSingles(int ID)
{
// Initialize your view model
EditSinglesVM model = new EditSinglesVM();
// Populate the SelectList's
ConfigureViewModel(model);
return View(model);
}
private void ConfigureViewModel(EditSinglesVM model)
{
model.PlayerList = db.Golfers().Select(g => new SelectListItem
{
Value = g.PlayerID.ToString(),
Text = string.Format("{0} {1}", g.FirstName, g.Surname)
});
model.CourseList = db.Courses().Select(c => new SelectListItem
{
Value = g.CourseID.ToString(),
Text = g.CourseName
});
}
and in the view
#model EditSinglesVM
#using(Html.BeginForm())
{
#Html.LabelFor(m => m.APlayerID)
#Html.DropDownListFor(m => m.APlayerID, Model.PlayerList, "-Please select-")
#Html.ValidationMessageFor(m => m.APlayerID)
....
#Html.LabelFor(m => m.CourseID)
#Html.DropDownListFor(m => m.CourseID, Model.CourseList, "-Please select-")
#Html.ValidationMessageFor(m => m.CourseID)
<input type="submit" ... />
}
and in the POST method
public ActionResult EditSingles(EditSinglesVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model); // repopulate SelectList's
return View(model(;
}
// Initialize a new data model
// Map the view model properties to it
// Save and redirect
}

ASP.NET MVC Relational DB

I have two models
public class Department
{
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
public string Image { get; set; }
public List<Teacher> Teachers { get; set; }
}
public class Teacher
{
public int TeacherID { get; set; }
public string TeacherName { get; set; }
public string TeacherLname { get; set; }
public int DepartmentID { get; set; }
public string Image { get; set; }
public Department Department { get; set; }
}
and I have a ViewModel
public class ViewModel
{
public List<Teacher> Teachers { get; set; }
public List<Department> Departments { get; set; }
}
I have a view where I'm displaying Departments
SchoolDbContext db = new SchoolDbContext();
public ActionResult Index()
{
ViewModel model = new ViewModel();
// retreive from database
model.Departments = db.Departments.ToList();
return View(model);
}
and on Details I want to display Teachers with a DepartmentID where I have a relation.
I'm trying to use this
public ActionResult Details(int id = 0)
{
ViewModel model = new ViewModel();
model.Departments = db.Departments.ToList();
model.Teachers = db.Teachers.Where(m => m.DepartmentID == m.DepartmentID);
return View(model);
}
but there is a error
Error 1 Cannot implicitly convert type 'System.Linq.IQueryable<_167School.Models.Teacher>' to 'System.Collections.Generic.List<_167School.Models.Teacher>'. An explicit conversion exists (are you missing a cast?) C:\Users\Admin\documents\visual studio 2013\Projects\167School\167School\Controllers\DepartmentsController.cs 33
Try this :
public ActionResult Details(int id = 0)
{
ViewModel model = new ViewModel();
model.Departments = db.Departments.ToList();
model.Teachers = db.Teachers.Where(m => m.DepartmentID == id).ToList();
return View(model);
}
You you have to return the Teacher entity as a list since its defined as a List in your ViewModel class.

ViewModel save selected value from dropdownlist

I have a dropdownlist - difficult. This is a dropdonwlinst where the user can select a value(easy, hard) but the value is not saved to the database, if I select a value. The strange thing I also have Country list, and that value is saved to the database.And If I put the values by hand in the database - for difficult the values are shown in the view
ModelVIew:
public RouteViewModel()
{
Countries = new List<SelectListItem>();
DifficultGrades = new List<SelectListItem>();
}
public int Id { get; set; }
[Required(ErrorMessage = "You need to give it a name")]
public string Name { get; set; }
public int SelectedValue { get; set; }
public int SelectedId { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
public IEnumerable<SelectListItem> DifficultGrades { get; set; }
}
public class Difficult
{
[Key]
public int DifficultId { get; set; }
public string DifficultName { get; set; }
public virtual ICollection<Route> Routes { get; set; }
}
public class Route
{
[Key]
public int routeID { get; set; }
public string Name { get; set; }
public int? UserProfileID { get; set; }
public int? CountryID { get; set; }
public int? DifficultGradeID { get; set; }
public virtual UserProfile userProfile { get; set; }
public virtual Country country { get; set; }
public virtual Difficult difficult { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(RouteViewModel routeViewModel )
{
try
{
if (ModelState.IsValid)
{
var route = new Route();
UpdateRoute(route, routeViewModel);
db.Routes.Add(route);
db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
catch (RetryLimitExceededException /* dex */)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
ViewBag.Id = new SelectList(db.countries, "Id", "country_name", routeViewModel.Id);
ViewBag.DifficultId = new SelectList(db.difficulties, "DifficultId", "DifficultName", routeViewModel.Id);
return View(new RouteViewModel());
}
and the update method:
public void UpdateRoute(Route route, RouteViewModel routeViewModel )
{
route.routeID = routeViewModel.Id;
route.Name = routeViewModel.Name;
route.CountryID = routeViewModel.Id;
route.DifficultGradeID = routeViewModel.Id;
// climb.country.country_name = ModelViewClimb.Name;
}
Thank you

Categories