I'm writing a simple tutorial app for my C# MVC class and our professor has us using some god awful in memory system using session and Lists because he hasn't started teaching entity framework yet
the problem I'm running into is that when i am trying to bind a dropdown list to my model it is giving me an unexpected result.
the code im using in the view is:
<div class="editor-label">
#Html.LabelFor(model => model.Author)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Author, new SelectList(new Lab2Repository().GetAuthors(), "Id", "Name"), "---- Select Category ----")
#Html.ValidationMessageFor(m=>m.Author)
</div>
<div class="editor-label">
#Html.LabelFor(m=>m.Category)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Category, new SelectList(new Lab2Repository().GetCategories(), "Id", "Name"), "---- Select Category ----")
#Html.ValidationMessageFor(m => m.Category)
</div>
and when i run that code it give a validation error no matter what is chosen
Repository Code:
using System;
using System.Linq;
using System.Collections.Generic;
using Int422.Lab2.Data;
using System.Web;
using Int422.Lab2.Models;
public class Lab2Repository
{
public Lab2Context Data { get; set; }
public Lab2Repository()
{
Data = (Lab2Context)HttpContext.Current.Application["State"];
}
#region Retrieval
public IEnumerable<Book> GetBooks()
{
return Data.Books;
}
public IEnumerable<Author> GetAuthors()
{
return Data.Authors.Select(obj => new Author(obj.Name)
{
Id = obj.Id,
Books = GetBooks().Where(b=>b.Author.Id == obj.Id).ToList()
});
}
public IEnumerable<Category> GetCategories()
{
return Data.Categories.Select(obj => new Category(obj.Name, obj.Description)
{
Id = obj.Id,
Books = GetBooks().Where(b=>b.Category.Id == obj.Id).ToList(),
});
}
#endregion
#region Singles
public Author GetAuthor(int id)
{
return GetAuthors().Where(obj => obj.Id == id).Single();
}
public Category GetCategory(int id)
{
return GetCategories().Where(obj => obj.Id == id).Single();
}
public Book GetBook(int id)
{
return Data.Books.Where(obj => obj.Id == id).Single();
}
#endregion
#region Edit
public void Edit(int id, Category rec)
{
if (id != rec.Id)
throw new InvalidOperationException("Id Mismatch during edit process");
int index = Data.Categories.IndexOf(Data.Categories.Single(p => p.Id == id));
if (index == -1)
throw new InvalidOperationException("Record not found no record to edit");
Data.Categories[index] = rec;
SaveChanges();
}
public void Edit(int id, Book rec)
{
if (id != rec.Id)
throw new InvalidOperationException("Id Mismatch during edit process");
int index = Data.Books.IndexOf(Data.Books.Single(p => p.Id == id));
if (index == -1)
throw new InvalidOperationException("Record not found no record to edit");
Data.Books[index] = rec;
SaveChanges();
}
public void Edit(int id, Author rec)
{
if (id != rec.Id)
throw new InvalidOperationException("Id Mismatch during edit process");
int index = Data.Authors.IndexOf(Data.Authors.Single(p => p.Id == id));
if (index == -1)
throw new InvalidOperationException(String.Format("Record id {0} not found", id));
Data.Authors[index] = rec;
SaveChanges();
}
#endregion
#region Create
//
public int Create(Category m)
{
m.Id = Data.Categories.Max(o => o.Id) + 1;
Data.Categories.Add(m);
SaveChanges();
return m.Id;
}
//adds new author to the collection returns the id
public int Create(Author m)
{
m.Id = Data.Authors.Max(o => o.Id) + 1;
Data.Authors.Add(m);
SaveChanges();
return m.Id;
}
public int Create(Book m)
{
m.Id = Data.Authors.Max(o => o.Id) + 1;
Data.Books.Add(m);
SaveChanges();
return m.Id;
}
#endregion
#region Delete
public void Delete(Author rec)
{
Data.Authors.Remove(Data.Authors.Single(o => o.Id == rec.Id));
SaveChanges();
}
public void Delete(Category m)
{
Data.Categories.Remove(Data.Categories.Single(o => o.Id == m.Id));
SaveChanges();
}
public void Delete(Book m)
{
Data.Books.Remove(Data.Books.Single(o => o.Id == m.Id));
SaveChanges();
}
#endregion
#region Session Persistance
public void SaveChanges()
{
//save to session
HttpContext.Current.Application["State"] = Data;
//refresh repo state from session
Data = (Lab2Context)HttpContext.Current.Application["State "];
}
#endregion
}
Models:
public class Author
{
public Author(string name)
{
Name = name;
}
public Author()
{
Books = new List<Book>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
public class Category
{
public Category(string name, string desc)
{
Name = name;
Description = desc;
Books = new List<Book>();
}
public Category()
{
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
public class Book
{
public Book(string title, Author author, Category category, double retailPrice, double cost)
{
Title = title;
Author = author;
Category = category;
RetailPrice = retailPrice;
Cost = cost;
}
public Book()
{
}
public int Id { get; set; }
public Category Category { get; set; }
public Author Author { get; set; }
public string Title { get; set; }
public double RetailPrice { get; set; }
public double Cost { get; set; }
}
Controller:
public partial class BooksController : Controller
{
private Lab2Repository repo = new Lab2Repository();
//
// GET: /Books/
public virtual ViewResult Index()
{
return View(repo.GetBooks());
}
//
// GET: /Books/Details/5
[GET("Books/{id:int}")]
public virtual ActionResult Details(int id)
{
Book book = repo.GetBook(id);
return View(book);
}
//
// GET: /Books/Create
public virtual ActionResult Create()
{
return View();
}
//
// POST: /Books/Create
[HttpPost]
public virtual ActionResult Create(Book book)
{
if (!ModelState.IsValid)
return View(book);
repo.Create(book);
return RedirectToAction(MVC.Books.Index());
}
//
// GET: /Books/Edit/5
public virtual ActionResult Edit(int id)
{
Book book = repo.GetBook(id);
return View(book);
}
//
// POST: /Books/Edit/5
[HttpPost]
public virtual ActionResult Edit(int id, Book book)
{
if (!ModelState.IsValid)
return View(book);
repo.Edit(id, book);
return RedirectToAction(MVC.Books.Details(id));
}
//
// GET: /Books/Delete/5
public virtual ActionResult Delete(int id)
{
Book book = repo.GetBook(id);
return View(book);
}
//
// POST: /Books/Delete/5
[HttpPost, ActionName("Delete")]
public virtual ActionResult DeleteConfirmed(int id)
{
Book book = repo.GetBook(id);
repo.Delete(book);
return RedirectToAction("Index");
}
}
Initializer:
public class Lab2StoreInitializer
{
public void Seed(Lab2Context c)
{
//add categories
var cat_Programming = new Category("Programming", "Books about writing computer code and developing software") { Id = 1 };
var cat_Politics = new Category("Politics", "books with politically charged subjects") { Id = 2 };
var cat_NonFiction = new Category("Non-Fiction", "Books about real life events") { Id = 3 };
c.Categories.Add(cat_Programming);
c.Categories.Add(cat_Politics);
c.Categories.Add(cat_NonFiction);
//add authors
var noamChomsky = new Author("Noam Chomsky") { Id = 1};
var howardZinn = new Author("Howard Zinn") { Id = 2 };
var scottHanselman = new Author("Scott Hanselman") { Id = 3 };
var philHaack = new Author("Phil Haack") { Id = 4 };
var danielleSteele = new Author("Danielle Steele") { Id = 5 };
var johnSkeet = new Author("John Skeet") { Id = 6 };
var johnResig = new Author("John Resig") { Id = 7 };
var scottKlein = new Author("Scott Klein") { Id = 8 };
c.Authors.Add(noamChomsky);
c.Authors.Add(howardZinn);
c.Authors.Add(scottHanselman);
c.Authors.Add(philHaack);
c.Authors.Add(danielleSteele);
c.Authors.Add(johnSkeet);
c.Authors.Add(johnResig);
c.Authors.Add(scottKlein);
// add books
c.Books.Add(new Book("Manufacturing Consent", noamChomsky, cat_Politics, 16.57, 12.00) { Id = 1 });
c.Books.Add(new Book("The Zinn Reader", howardZinn, cat_Politics, 35.75, 30.00) { Id = 2 });
c.Books.Add(new Book("C# In Depth", johnSkeet, cat_Programming, 29.99, 25.00) { Id = 3 });
c.Books.Add(new Book("Professional ASP.NET MVC 2", scottHanselman, cat_Programming, 34.99, 30.00) { Id = 4 });
c.Books.Add(new Book("Professional MVC 4", philHaack, cat_Programming, 49.99, 45.00) { Id = 5 });
c.Books.Add(new Book("His Bright Light: The Story of Nick Traina", danielleSteele, cat_NonFiction, 19.99, 14.00) { Id = 6 });
c.Books.Add(new Book("Secrets of the JavaScript Ninja", johnResig, cat_Programming, 34.99, 29.99) { Id = 7 });
c.Books.Add(new Book("Professional LINQ", scottKlein, cat_Programming, 39.99, 35.00) { Id = 8 });
c.Books.Add(new Book("jQuery in Action", johnResig, cat_Programming, 49.99, 43.00) { Id = 9 });
HttpContext.Current.Application["State"] = c;
//base.Seed(c);
}
}
#Html.DropDownListFor(m => m.Author.Id, new SelectList(new Lab2Repository().GetAuthors(), "Id", "Name"), "---- Select Category ----")
The SelectList is using the Id property of the Author to identify it within a Book. However, your Book model has it defined as:
public Author Author { get; set; }
The default model binder won't know how to associate the Id with an Author. To fix this, you can declare it like so:
public int Author { get; set; }
Since Id and Author are now the same data type (int), it will work. The same goes for Category:
public int Category { get; set; }
Your alternative is to write your own model binder and register it with MVC. Then you can force it to load an entire Author object when only an int is passed through from the dropdown list. See this question for some suggestions with that: ASP.Net MVC Custom Model Binding explanation
Related
Its crashing on my CardDetailsView,the Details IActionResult in my CardsController
CardDetailsView-
public class CardDetailsViewModel
{
public string Id { get; set; }
public string Title { get; set; }
public string ImageUrl { get; set; }
public string Destination { get; set; }
public string Model { get; set; }
public string SNumber { get; set; }
public string QNumber { get; set; }
}
CardDetailsView-
#model CardDetailsViewModel
#{ ViewBag.Title = "Details"; }
Card Details
Title
Destination
Model
SNumber
QNumber
Details
CardsController-
public class CardsController : Controller
{
public readonly DigitalCardsDbContext data;
public CardsController(DigitalCardsDbContext data)
{
this.data = data;
}
public IActionResult Add() => View();
[HttpPost]
public IActionResult Add(CardAddViewModel card)
{
if(!ModelState.IsValid)
{
return View(card);
}
var cardd = new Card
{
Title = card.Title,
ImageUrl = card.ImageUrl,
Destination = card.Destination,
Receiver = card.Receiver,
Model = card.Model,
UserFullName = card.UserFullName,
SNumber = card.SNumber,
QNumber = card.QNumber,
PublicView = card.PublicView
};
this.data.Cards.Add(cardd);
this.data.SaveChanges();
return RedirectToAction("All","Cards");
}
public IActionResult All()
{
var cards = this.data.Cards
.Where(c => c.PublicView == true).ToList();
var usern = User.Identity.Name;
if(usern!=this.User.Identity.Name)
{
return BadRequest();
}
var cardsl = cards
.Select(c => new CardAllViewModel
{
Id = c.Id,
Title = c.Title,
ImageUrl = c.ImageUrl,
Destination = c.Destination,
SNumber = c.SNumber,
QNumber = c.QNumber
})
.ToList();
return View(cardsl);
}
public IActionResult Details(string cardId)
{
var card = this.data.Cards.Where(c => c.Id == cardId)
.Select(c => new CardDetailsViewModel
{
Id = c.Id,
ImageUrl = c.ImageUrl,
Title = c.Title,
Destination = c.Destination,
Model = c.Model,
SNumber = c.SNumber,
QNumber = c.QNumber
})
.SingleOrDefault();
return View(card);
}
The code is crashing on my View,on every div class,Title,ImageUrl,Etc.The exception is Microsoft.AspNetCore.Mvc.Razor.RazorPage.Model.get returned null.
Here is snap-Error
Please verify the value in the image [url] it looks like that could be the reason.
I have a ViewModel and I would like to make a fonctionnal delete(GET) and deleteConfirmed(POST) so i can delete what ever data is stored in my DB
I don’t know and would like to know what step to take to complete the deleteConfirmed. There is normally auto-generated code but it’s not what I need.
here is my ViewModel
using System;
using ExploFormsDB.Models;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ExploFormsDB.ViewModels
{
public class WorkShiftDetailViewModel
{
[Key]
public int WorkShiftId { get; set; }
public int? HoleId { get; set; }
public string HoleName { get; set; }
public int SurveyLocationId { get; set; }
public int SupplierId { get; set; }
public int ZoneId { get; set; }
public string SurveyLocation1 { get; set; }
public string SupplierName { get; set; }
public string ZoneName { get; set; }
public DateTime StartDay { get; set; }
public DateTime EndDay { get; set; }
public ICollection<WorkerViewModel> WorkShiftEmployees { get; set; }
}
}
Here is my Controller, i have included the Create to help have a better understanding. GET: Delete seems to be working correctly, i am having trouble with the Post. any help what so ever will do. if the question as been answered already please send me a link. I'm pretty new to c# and core and completly new to ViewModels
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(WorkShiftDetailViewModel workShiftDetailViewModel)
{
if (!ModelState.IsValid)
{
WorkShift ws = new WorkShift();
ws.StartDay = workShiftDetailViewModel.StartDay;
ws.EndDay = workShiftDetailViewModel.EndDay;
ws.SupplierId = workShiftDetailViewModel.SupplierId;
ws.SurveyLocationId = 1;
ws.ZoneId = workShiftDetailViewModel.ZoneId;
ws.HoleId = workShiftDetailViewModel.HoleId;
_context.Add(ws);
await _context.SaveChangesAsync();
foreach (WorkerViewModel member in workShiftDetailViewModel.WorkShiftEmployees)
{
if (member.isDeleted == false) {
WorkShiftTeam emp = new WorkShiftTeam();
emp.EmployeeId = member.EmployeeId;
emp.RoleId = member.RoleId;
emp.WorkShiftId = ws.WorkShiftId;
_context.Add(emp);
}
}
HttpContext.Session.SetInt32("wsId", ws.WorkShiftId);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(CreateSharedView));
}
return View(workShiftDetailViewModel);
}
public IActionResult Delete(int? id)
{
if (id == null)
{
return NotFound();
}
List<WorkerViewModel> Workers = new List<WorkerViewModel>();
WorkShift ws = _context.WorkShift.Include(w => w.WorkShiftTeam).SingleOrDefault(x => x.WorkShiftId == id);
WorkShiftDetailViewModel detail = new WorkShiftDetailViewModel();
detail.HoleName = ws.HoleId == null ? "N/A" : _context.Hole.Find(ws.HoleId).HoleName;
detail.StartDay = ws.StartDay;
detail.EndDay = ws.EndDay;
detail.ZoneName = _context.Zone.Find(ws.ZoneId).ZoneName;
detail.SurveyLocation1 = _context.SurveyLocation.Find(ws.SurveyLocationId).SurveyLocation1;
detail.SupplierName = _context.Supplier.Find(ws.SupplierId).SupplierName;
detail.WorkShiftId = ws.WorkShiftId;
int order = 0;
var rolelist = new SelectList(_context.Role, "RoleId", "Role1");
var empsWithFullName = from e in _context.Employee.Where(a => a.IsActive)
select new
{
ID = e.EmployeeId,
FullName = e.LastName + ", " + e.FirstName
};
var empList = new SelectList(empsWithFullName, "ID", "FullName");
foreach (WorkShiftTeam member in ws.WorkShiftTeam.OrderBy(a => a.EmployeeId))
{
Workers.Add(new WorkerViewModel() { EmployeeId = member.EmployeeId, RoleId = member.RoleId, Index = order, Roles = rolelist, Employees = empList });
order++;
}
detail.WorkShiftEmployees = Workers;
return View(detail);
}
// POST: WorkShiftDetailViewModels/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
//??
} ```
Why you created an extra method for delete action as HttpGet? (that occurred conflict)
change it to:
[HttpGet]
public IActionResult GetById(int? id) { ... }
and just one delete method with this definition
[HttpPost]
public async Task<IActionResult> Delete(int? id) { ... }
I am new in ASP.NET core and EF core. Please check my code and let me know what I am doing wrong.
** Foreign key constraint violation for AuthorId.
** BookCategory entity can not be tracked because another instance with same ID is being tracked
Book Model
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public double Price { get; set; }
public int? Discount { get; set; }
public string ImagePath { get; set; }
public int? Stock { get; set; }
public Author Author { get; set; }
public int AuthorId { get; set; }
public BookCategory Category { get; set; }
public int? CategoryId { get; set; }
public ICollection<JoinBookTag> BookTags { get; set; }
}
BookCategory Model
public class BookCategory
{
public int Id { get; set; }
[Display(Name = "Category Name")]
public string CategoryName { get; set; }
public ICollection<Book> Books { get; set; }
}
Author Model
public class Author
{
public int AuthorId { get; set; }
public string Name { get; set; }
public ICollection<Book> Books { get; set; }
}
BookController
private readonly ApplicationDbContext _db;
private readonly HostingEnvironment _hostingEnvironment;
[BindProperty]
public BookViewModel ViewModel { get; set; }
public BookController(ApplicationDbContext db, HostingEnvironment host)
{
_db = db;
_hostingEnvironment = host;
ViewModel = new BookViewModel()
{
Book = new Models.Book(),
Authors = _db.Authors.ToList(),
BookCategories = _db.BookCategories.ToList(),
Tags = _db.Tags.ToList()
};
}
...............
[HttpGet]
public IActionResult Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var book = _db.Books.Include(b => b.Category)
.Include(b => b.Author)
.SingleOrDefault(b => b.BookId == id);
if (book == null)
{
return NotFound();
}
ViewModel.Book = book;
return View(ViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(BookViewModel model, int? id)
{
if (id == null)
{
return NotFound();
}
if (id != model.Book.BookId)
{
return NotFound();
}
if (!ModelState.IsValid)
{
/*ViewModel.Book = model.Book;
return View(ViewModel);*/
var errors = ModelState.Select(x => x.Value.Errors)
.Where(y => y.Count > 0)
.ToList();
return Json(new { errors });
}
var dbModel = _db.Books.Include(b => b.Category).Where(b => b.BookId == id).FirstOrDefault();
var file = HttpContext.Request.Form.Files;
if (file.Count > 0)
{
var RootDirectory = _hostingEnvironment.WebRootPath;
var extension = Path.GetExtension(file[0].FileName);
var filePath = Path.Combine(DataContext.ImageDirectory, model.Book.BookId + extension);
using (var fileStream = new FileStream(Path.Combine(RootDirectory, filePath), FileMode.Create))
{
file[0].CopyTo(fileStream);
}
dbModel.ImagePath = #"/" + filePath;
}
dbModel.AuthorId = model.Book.AuthorId;
dbModel.CategoryId = model.Book.CategoryId;
dbModel.Discount = model.Book.Discount;
dbModel.Price = model.Book.Price;
dbModel.Stock = model.Book.Stock;
dbModel.Title = model.Book.Title;
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
You need to add the key attribute on your id properties inside your models.
The next thing you need to update is tell _db to update your entity first then and only then save changes.
Why are you using async and await? Are these controller actions slowing down the UI?
Also can you post your book view model?
You action methods are wrong in certain places. Let me know if you want some more detailed advice.
[HttpGet]
public IActionResult Edit(int? id)
{
//Give this a name other than view model for example BookViewModel
ViewModel model = new ViewModel();
if (id == null)
{
return NotFound();
}
var book = _db.Books.Include(b => b.Category)
.Include(b => b.Author)
.SingleOrDefault(b => b.BookId == id);
if (book == null)
{
return NotFound();
}
model.Book = book;
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(BookViewModel model, int? id)
{
if (id == null || id != model.Book.BookId)
{
return NotFound();
}
if (ModelState.IsValid)
{
var dbModel = _db.Books.Include(b => b.Category).Where(b => b.BookId == id).FirstOrDefault();
var files = HttpContext.Request.Form.Files;
if (files.Any())
{
var RootDirectory = _hostingEnvironment.WebRootPath;
var extension = Path.GetExtension(files[0].FileName);
var filePath = Path.Combine(DataContext.ImageDirectory, model.Book.BookId + extension);
using (var fileStream = new FileStream(Path.Combine(RootDirectory, filePath), FileMode.Create))
{
file[0].CopyTo(fileStream);
}
dbModel.ImagePath = #"/" + filePath;
}
dbModel.AuthorId = model.Book.AuthorId;
dbModel.CategoryId = model.Book.CategoryId;
dbModel.Discount = model.Book.Discount;
dbModel.Price = model.Book.Price;
dbModel.Stock = model.Book.Stock;
dbModel.Title = model.Book.Title;
await _db.Books.UpdateAsync(dbModel);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(model);
}
In an Action Result that does a HttpPost i get an error from EF
"ModelState.Errors Internal error in the expression evaluator"
My model in View is OrdineOmaggio
public partial class OrdineOmaggio
{
public int Id { get; set; }
public string Id_Gioielleria { get; set; }
public System.DateTime Data_Ordine { get; set; }
public virtual Consumatore MD_CONSUMATORE { get; set; }
public virtual Omaggio MD_OMAGGIO { get; set; }
public virtual CodiceRandomConsumatore MD_RANDOM_CONSUMATORE { get; set; }
}
My Action is so
public async Task<ActionResult> ChooseGift(
[Bind(Include ="Data_Ordine,MD_RANDOM_CONSUMATORE,MD_OMAGGIO,Id_Gioielleria")]
OrdineOmaggio ordineOmaggio,
string codiceOmaggio, string codice)
{
var randomConsumatore = _context.CodiciRandomConsumatori
.SingleOrDefault(c => c.Codice == codice) ??
new CodiceRandomConsumatore
{
Id = -1,
Codice = "",
Assegnato = null,
Distinzione = ""
};
var consumatore = _context.CodiciRandomConsumatori
.Where(c => c.Codice == codice)
.Select(c => c.MD_CONSUMATORE)
.SingleOrDefault();
var omaggio = _context.Omaggi
.SingleOrDefault(c => c.CodiceOmaggio == codiceOmaggio);
if (ModelState.IsValid)
{
ordineOmaggio.Data_Ordine = DateTime.Now;
ordineOmaggio.Id_Gioielleria = ordineOmaggio.Id_Gioielleria;
ordineOmaggio.MD_CONSUMATORE = consumatore; // FK
ordineOmaggio.MD_OMAGGIO = omaggio; // FK
ordineOmaggio.MD_RANDOM_CONSUMATORE = randomConsumatore; // FK
_context.OrdiniOmaggio.Add(ordineOmaggio);
randomConsumatore.Assegnato = true;
_context.SaveChanges();
return RedirectToAction("Success");
}
return View(ordineOmaggio);
}
The error is about dataAnnotation: it say that not all field all filled
The metadata is
public class OrdineOmaggioMetadata
{
[Required(ErrorMessage = "Scegli la gioiellereia.")]
public string Id_Gioielleria;
[Required(ErrorMessage = "Seleziona una foto.")]
public Omaggio MD_OMAGGIO;
...
}
In my view i placed
#Html.HiddenFor(m=> m.MD_OMAGGIO.CodiceOmaggio)
#Html.ValidationMessageFor(m => m.MD_OMAGGIO.CodiceOmaggio)
but this helper pass null to ActionResult
MD_OMAGGIO is a table foreign key for product codes.
what i wrong ?
I have two Listboxes where you can move exercises from an available list of exercises to a list of selected exercises for a specific user. My current problem is that my selected list (aka RegimeItems) shows the exercises for all of the users.
I believe the problem lies in ChosenExercises(at the bottom of controller) i am also getting a null reference exception at:
var regimeIDs = model.SavedRequested.Split(',').Select(x => int.Parse(x));
Controller.cs
[HttpGet]
public ActionResult ExerciseIndex(int? id, UserExerciseViewModel vmodel)
{
User user = db.Users.Find(id);
user.RegimeItems = ChosenExercises();
UserExerciseViewModel model = new UserExerciseViewModel { AvailableExercises = GetAllExercises(), RequestedExercises = ChosenExercises(user, vmodel) };
user.RegimeItems = model.RequestedExercises;
return View(model);
}
[HttpPost]
public ActionResult ExerciseIndex(UserExerciseViewModel model, string add, string remove, string send, int id)
{
User user = db.Users.Find(id);
user.RegimeItems = model.RequestedExercises;;
RestoreSavedState(model);
if (!string.IsNullOrEmpty(add))
AddExercises(model, id);
else if (!string.IsNullOrEmpty(remove))
RemoveExercises(model, id);
SaveState(model);
return View(model);
}
void SaveState(UserExerciseViewModel model)
{
model.SavedRequested = string.Join(",", model.RequestedExercises.Select(p => p.RegimeItemID.ToString()).ToArray());
model.AvailableExercises = GetAllExercises().ToList();
}
void RestoreSavedState(UserExerciseViewModel model)
{
model.RequestedExercises = new List<RegimeItem>();
//get the previously stored items
if (!string.IsNullOrEmpty(model.SavedRequested))
{
string[] exIds = model.SavedRequested.Split(',');
var exercises = GetAllExercises().Where(p => exIds.Contains(p.ExerciseID.ToString()));
model.AvailableExercises.AddRange(exercises);
}
}
private List<Exercise> GetAllExercises()
{
return db.Exercises.ToList();
}
private List<RegimeItem> ChosenExercises(User user, UserExerciseViewModel model)//RegimeItem regimeItem)
{
var regimeIDs = model.SavedRequested.Split(',').Select(x => int.Parse(x));
return db.RegimeItems.Where(e => regimeIDs.Contains(e.RegimeItemID)).ToList();
//return db.Users.Where(r => r.RegimeItems = user.UserID);
//return db.Users.Where(r => r.RegimeItems.RegimeItemID == user.UserID);
}
Models
public class User
{
public int UserID { get; set; }
public ICollection<RegimeItem> RegimeItems { get; set; }
public User()
{
this.RegimeItems = new List<RegimeItem>();
}
}
public class RegimeItem
{
public int RegimeItemID { get; set; }
public Exercise RegimeExercise { get; set; }
}
ViewModel
public class UserExerciseViewModel
{
public List<Exercise> AvailableExercises { get; set; }
public List<RegimeItem> RequestedExercises { get; set; }
public int? SelectedExercise { get; set; }
public int[] AvailableSelected { get; set; }
public int[] RequestedSelected { get; set; }
public string SavedRequested { get; set; }
}
Try changing
return db.Users.Where(r => r.RegimeItems = user.UserID);
to
return db.Users.Where(r => r.RegimeItems.RegimeItemID == user.UserID);
Because the way I read it you're currently trying to match an int with an object.
edit: Another error was resulted which the OP found himself.
"It seems that RegimeItems is a collection of RegimeItem - it does not have a have a single ID. So it needed to be .Where(u => u.UserID == user.UserID) and then to select the regimeItems associated with the user .SelectMany(u => u.RegimeItems).ToList(); Thanks for your help, if you update your answer with that i will mark yours as the correct answer." -Nilmag
Firstly, you're going to want to update the calls to ChosenExercises() in ExcerciseIndex(int? id) to pass in the user like this: ChosenExercises(user).
Secondly, the conversion error is because you are comparing r.RegimeItems to the User ID, which is an int. In order to return a list of regime items for the user you'll need to query the Excercises table, rather than the users table:
private List<RegimeItem> ChosenExercises(User user)//RegimeItem regimeItem)//User user, RegimeItem regimeItem)
{
var regimeIDs = user.SavedRequested.Split(',').Select(x=>int.Parse(x));
return db.RegimeItem.Where(e=> regimeIDs.Contains(e.RegimeItemID)).ToList();
}