Issue with SelectList - NullReferenceException - c#

I have set up a SelectList to select an album when creating a track for the chinook database. Following Microsoft docs instruction, for some reason (that I can't see as I'm still trying to learn) it doesn't like what I am putting in my view on razor pages. The code for the walk through is below.
Entities:
public class Album
{
public int AlbumId { get; set; }
public string Title { get; set; }
public int ArtistId { get; set; }
//related entities
public virtual ICollection<Track> Tracks { get; set; }
public virtual Artist Artist { get; set; }
}
public class Track
{
public int TrackId { get; set; }
public string Name { get; set; }
public int AlbumId { get; set; }
public string Composer { get; set; }
public int Milliseconds { get; set; }
public int Bytes { get; set; }
public double UnitPrice { get; set; }
public int MediaTypeId { get; set; }
public int GenreId { get; set; }
//related entities
public virtual Album Album { get; set; }
}
Creating the model for SelectedList:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using UWS.Project;
namespace Project.Pages.Albums
{
public class AlbumPageModel : PageModel
{
public SelectList AlbumNameSL { get; set; }
public void PopulateAlbumsDropDownList(Chinook db,
object selectedAlbum = null)
{
var albumsQuery = from a in db.Albums
orderby a.Title // Sort by name.
select a;
AlbumNameSL = new SelectList(albumsQuery,
"AlbumId", "Title", selectedAlbum);
}
}
}
Now my Model for creating the track:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using UWS.Project;
namespace Project.Pages.Albums
{
public class TrackCreateModel : AlbumPageModel
{
private Chinook db;
public TrackCreateModel(Chinook injectedContext)
{
db = injectedContext;
}
public IActionResult OnGet(int? id)
{
PopulateAlbumsDropDownList(db);
return Page();
}
[BindProperty]
public Track Track { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var emptyTrack = new Track();
if (await TryUpdateModelAsync<Track>(
emptyTrack,
"track", // Prefix for form value.
s => s.AlbumId, s => s.Name, s => s.Composer, s => s.Milliseconds, s => s.Bytes, s
=> s.MediaTypeId, s => s.GenreId, s => s.UnitPrice))
{
db.Tracks.Add(emptyTrack);
await db.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select AlbumId if TryUpdateModelAsync fails.
PopulateAlbumsDropDownList(db, emptyTrack.AlbumId);
return Page();
}
}
}
Trying to implement the SelectList in my view:
Being new to this I cannot for the life of me see the issue. I have looked at previous issues on here with SelectedList's but none relate to my issue. Any help would be appreciated.

Do not enter selectedValue in the PopulateAlbumsDropDownList method in AlbumPageModel
Currently you either leave it blank or provide an id, but that's not going to work anyway

Related

EF6 Not Working After Column Change [Invalid Column]

I have several classes in my real code but for this problem I will focus on the two at hand. I have a List class which contains a Name and Items. There is also a Group class which has a name and Items. The relationship used to be List -> Group (many) -> Items. The default for our data seemed to trend more toward List -> Items (many) -> Group where an item may, or may not, be grouped. To accomplish this I simply removed the ListId and navigational item from the Group class. I am able to load the Items just fine but whenever I try to access the Groups DbSet it gives me the following error:
Invalid column name 'List_ListId'.
Here is the code for the classes and the DbContext. I am using EF6 (not core). I have tried recreating the Group class, restarting Visual Studio, restarting SQL Server, and wiping the publish directory to make sure it is clean. Help?
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
namespace MyProject.Database
{
[Table("dbo.Lists")]
public class List
{
[Key]
public int ListId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public bool SortAsNumeric { get; set; }
public virtual List<ListItem> Items { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
namespace MyProject.Database
{
[Table("dbo.ListGroups")]
public class ListGroup
{
[Key]
public int ListGroupId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int OrderSequence { get; set; }
[NotMapped]
public List<ListItem> Items { get; set; }
public ListGroup()
{
this.Items = new List<ListItem>();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace MyProject.Database
{
[Table("dbo.ListItems")]
public class ListItem
{
[Key]
public int ListItemId { get; set; }
[Required]
public string Label { get; set; }
[Required]
public string Value { get; set; }
public string Subtext { get; set; }
public string Icon { get; set; }
public string Thumbnail { get; set; }
public int OrderSequence { get; set; }
[NotMapped]
public bool Selected { get; set; }
public int ListId { get; set; }
public virtual List List { get; set; }
public int? ListGroupId { get; set; }
public virtual ListGroup Group { get; set; }
public virtual List<ListItemProperty> Properties { get; set; }
public ListItem()
{
this.OrderSequence = 1;
this.Selected = false;
this.Properties = new List<ListItemProperty>();
}
}
}
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web.Mvc;
namespace MyProject.Database
{
public class ListContext : DbContext
{
public ListContext() : base("MyConnectionString") {}
public virtual DbSet<List> Lists { get; set; }
public virtual DbSet<ListItem> Items { get; set; }
public virtual DbSet<ListGroup> Groups { get; set; }
public virtual DbSet<ListItemProperty> Properties { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<List>()
.HasMany(l => l.Items)
.WithRequired(li => li.List)
.HasForeignKey<int>(li => li.ListId);
modelBuilder.Entity<ListItem>()
.HasMany(li => li.Properties)
.WithRequired(p => p.Item)
.HasForeignKey<int>(p => p.ListItemId);
}
}
}
NOTE: The following code is working. The problem comes when I attempt to access this.Groups in the context.
List MyList = Lists
.Where(x => x.Name == ListName)
.Include(x => x.Items.Select(i => i.Properties))
.SingleOrDefault();

How to fix Entity Framework Eager loading coming out blank or null

I set up my database with two tables Reports and Expenses
Joined on ReportId
I can not seem for the life of me get the expenses to come out without.
Spent a few days in tutorials.
using ExpenseAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace ExpenseAPI.Data
{
public class ReportsDbContext : DbContext
{
public ReportsDbContext(DbContextOptions<ReportsDbContext> options):base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
System.Console.Out.WriteLine("on model create");
/* Expense composite key */
modelBuilder.Entity<Expense>()
.HasKey(c => new { c.ReportId, c.ExpenseId });
/* Reports to Expenses one to many */
modelBuilder.Entity<Reports>()
.HasMany(e => e.Expenses)
.WithOne(r => r.Report)
.HasPrincipalKey(e => e.ReportId);
}
public DbSet<Reports> Reports { get; set; }
}
}
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ExpenseAPI.Models
{
public class Reports
{
public Reports()
{
Expenses = new List<Expense>();
}
[Key]
public int ReportId { get; set; }
[Required]
public string ReportName { get; set; }
public ICollection<Expense> Expenses { get; set; }
}
}
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ExpenseAPI.Models
{
public class Expense
{
[Key, Column(Order = 0)]
public int ReportId { get; set; }
[Key, Column(Order = 2)]
public int ExpenseId { get; set; }
[Required]
public DateTime Date { get; set; }
[Required]
public decimal Amount { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Payee { get; set; }
public Reports Report { get; set; }
}
}
using System.Linq;
using ExpenseAPI.Data;
using ExpenseAPI.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace ExpenseAPI.Controllers
{
[Route("api/reports")]
[ApiController]
public class ReportsController : ControllerBase
{
ReportsDbContext reportsDbContext;
public ReportsController(ReportsDbContext _reportsDbContex)
{
reportsDbContext = _reportsDbContex;
}
// GET: api/Reports
[HttpGet]
public IActionResult Get()
{
var result = reportsDbContext.Reports;
result.Include("Expenses");
return Ok(result);
// ISSUE IS HERE expenses is empty
}
}
}
Result:
[{"reportId":1,"reportName":"August Expense 2019-08","expenses":[]}]
Expected:
[{"reportId":1,"reportName":"August Expense 2019-08","expenses":[
{Expense Data Here}
]}]
Before someone says make sure there is data in expenses, there is a expense record that does have the ReportId of 1
Check the debug console.
Would have noticed an error
//If using ASP.NET Core MVC, add this to the ConfigureServices method of your startup.cs file:
services.AddMvc()
.AddJsonOptions(
options => options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

Dynamic DropDown list in MVC

I am very new to MVC and I am trying to make a CreateEmployee form in MVC. for now, all I am trying to achieve is to add the poulated dropdownlist for Departments to the form. the dropdownlist is populated from a database, and using Visual Studio, I connected to the DB and it created all the code file for the table. This is what the create form should look like. The form below is created using Angular js.
here is my Createform model.
public class CreateEmployee
{
public int Id { get; set; }
public string FullName { get; set; }
[Required]
public string Notes { get; set; }
//add the dropdown list of departments here,i not sure on what to do here
//do i create an instance of dbcontext here or AngtestDepartment
public bool PerkCar { get; set; }
public bool PerkStock { get; set; }
public bool PerkSixWeeks { get; set; }
public string PayrollType { get; set; }
}
public ActionResult CreateEmployee()
{
return View();
}
Here are the table codes that visual studio generated
Department Table
using System;
using System.Collections.Generic;
public partial class AngTestDepartment
{
public int id { get; set; }
public string Department { get; set; }
}
and the Department Table context
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class DepartmentDbContext : DbContext
{
public DepartmentDbContext()
: base("name=DepartmentDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<AngTestDepartment> AngTestDepartments { get; set; }
public System.Data.Entity.DbSet<AngularForms2.Models.CreateEmployee> CreateEmployees { get; set; }
}
You should query the DB in the controller and supply that to the View, e.g. via the model:
Add the following to your model:
public int Department { get; set; }
public IEnumerable<AngTestDepartment> Departments { get; set; }
and in your Action:
public ActionResult CreateEmployee()
{
using (var db = new DepartmentDbContext())
{
var model = new CreateEmployee();
model.Departments = db.AngTestDepartments.ToList();
return View(model);
}
}
then inside your view you can do something like:
#Html.DropDownListFor(m => m.Department,
Model.Departments.Select(d => new SelectListItem()
{
Value = d.id.ToString(),
Text = d.Department
}))

Dictionary error while passing a class in to a cshtml file

I was trying to pass 2 classes in to the one cshtml file and kept getting an error I was passing a model "of type 'JavaTutorial.Models.Quiz', but this dictionary requires a model item of type 'JavaTutorial.Models.Evaluation'."
I don't get it, I'm after creating a seperate class and am now just trying to pass in one class but still the error appears.
I have a class Evaluation to which I'm trying to call upon in the cshtml but a Quiz class keeps interfering but I have no idea why..
cshtml:
#model JavaTutorial.Models.Evaluation
<h2>Details</h2>
<h2>Evaluation</h2>
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.Questions)
<input type="submit" />
}
Evaluation.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.ComponentModel.DataAnnotations;
namespace JavaTutorial.Models
{
public class Evaluation
{
public List<Question> Questions { set; get; }
public Evaluation()
{
Questions = new List<Question>();
}
}
}
Quiz.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.ComponentModel.DataAnnotations;
namespace JavaTutorial.Models
{
public class Quiz
{
[Key]
public int QuizId { get; set; }
public string Title { get; set; }
public int difficulty { get; set; }
public string description { get; set; }
public Genre Genre { get; set; }
}
public class Question
{
public int ID { set; get; }
public string QuestionText { set; get; }
public List<Answer> Answers { set; get; }
[Required]
public string SelectedAnswer { set; get; }
public Question()
{
Answers = new List<Answer>();
}
}
public class Answer
{
public int ID { set; get; }
public string AnswerText { set; get; }
}
/* public class Evaluation
{
public List<Question> Questions { set; get; }
public Evaluation()
{
Questions = new List<Question>();
}
}*/
/*public class ParentView
{
public Quiz Quiz { get; set; }
public Question Question { get; set; }
public Answer Answer { get; set; }
public Evaluation Evaluation{ get; set; }
}
*/
/*
* using (Html.BeginForm())
{
#Html.EditorFor(x => x.Evaluation.Questions)
<input type="submit" />
}*/
}
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JavaTutorial.Models;
//using ViewModels;
namespace JavaTutorial.Controllers
{
public class QuizController : Controller
{
//
// GET: /Quiz/
TutorialEntities storeDB = new TutorialEntities();
public ActionResult Details(int id)
{
var quiz = storeDB.Quizzes.Find(id);
return View(quiz);
}
You have set model in view:
#model JavaTutorial.Models.Evaluation
but you are not passing this model:
JavaTutorial.Models.Quiz
View expects the Model Class Evaluation but you are passing Quiz class
If you want to pass Quiz Model change in View like this:
#model JavaTutorial.Models.Quiz
If you want to pass two models, create a viewmodel and it in a folder named ViewModels in your solution.
public class MyViewModel
{
public List<Question> Questions { set; get; }
public List<Quiz> Quizzes{ set; get; }
public List<Answer> Asnwers { set; get; }
}
ans pass thie view model to your view and set in view like this:
#model JavaTutorial.ViewModels.MyViewModel

Issue: Cannot reference -- The name 'Compeditors' does not exsist in the current context

Error: The name 'Compeditors' does not exsist in the current context
Newbie to MVC 4 and trying to get the complete right way to get it done. With the MVC arch I am also using an interface. Everything was going great until I tried to code to add data to the database. I have a view for the data add, the controller to accept the view and the model to get the data into the database as expected. There are 2 Name Spaces. eManager.Core and eManager.Web2
Just tried everything I can think of, but the Compeditors collection cannot be found.. any ideas would be greatly apprtiated!!
//Compeditor Class in eManager.Core -- Compeditor.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace eManager.Core
{
public class Compeditor
{
[Key]
public virtual int CompeditorId { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string MiddleInt { get; set; }
public virtual string StreetAddress { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string PostalCode { get; set; }
public virtual string EmailAddress { get; set; }
public virtual string HomePhone { get; set; }
public virtual string CellPhone { get; set; }
public virtual int Height { get; set; }
public virtual int Weight { get; set; }
}
}
//DB Access Setup - BodyBuilderDB.cs in eManager.Web2
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using eManager.Core;
namespace eManager.Web2.Infastructure
{
public class BodyBuilderDB : System.Data.Entity.DbContext, IBodyBuilderDataSource
{
public BodyBuilderDB() : base("DefaultConnection")
{
}
public DbSet<Class_Type> Class_Types { get; set; }
public DbSet<Compeditor> Compeditors { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<Event_Class> Event_Classes { get; set; }
IQueryable<Compeditor> IBodyBuilderDataSource.Compeditors
{
get
{ return Compeditors; }
}
IQueryable<Event_Class> IBodyBuilderDataSource.Event_Classes
{
get
{ return Event_Classes; }
}
IQueryable<Event> IBodyBuilderDataSource.Events
{
get
{ return Events; }
}
IQueryable<Class_Type> IBodyBuilderDataSource.Class_Types
{
get
{ return Class_Types; }
}
void IBodyBuilderDataSource.Save()
{
SaveChanges();
}
}
}
//CompeditorController.cs -- Area I am having the issue in eManager.Web2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using eManager.Core;
using eManager.Web2.Models;
namespace eManager.Web2.Controllers
{
public class CompeditorController : Controller
{
private readonly IBodyBuilderDataSource _db;
public CompeditorController(IBodyBuilderDataSource db)
{
_db = db;
}
[HttpGet]
public ActionResult Create()
{
var model = new CreateCompeditorViewModel();
return View();
}
[HttpPost]
public ActionResult Create(CreateCompeditorViewModel viewModel)
{
var compeditor = new Compeditor();
{
if (ModelState.IsValid)
compeditor.CompeditorId = viewModel.CompeditorId;
compeditor.FirstName = viewModel.FirstName;
compeditor.MiddleInt = viewModel.MiddleInt;
compeditor.LastName = viewModel.LastName;
compeditor.StreetAddress = viewModel.StreetAddress;
compeditor.City = viewModel.City;
compeditor.State = viewModel.State;
compeditor.PostalCode = viewModel.PostalCode;
compeditor.HomePhone = viewModel.HomePhone;
compeditor.CellPhone = viewModel.CellPhone;
compeditor.Height = viewModel.Height;
compeditor.Weight = viewModel.Weight;
compeditor.EmailAddress = viewModel.EmailAddress;
Compeditors.add(compeditor); // "The name 'Compeditors' does not exsist in the current context
_db.Save();
}
return View(viewModel);
}
}
}
//IBodyBuilderDataSource: the Interface in eManager.Core
using eManager.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace eManager.Core
{
public interface IBodyBuilderDataSource
{
IQueryable<Compeditor> Compeditors { get; }
IQueryable<Event_Class> Event_Classes { get; }
IQueryable<Event> Events { get; }
IQueryable<Class_Type> Class_Types { get; }
void Save();
}
}
//CreateCompeditorViewModel.cs -- View of the data add
using eManager.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace eManager.Core
{
public interface IBodyBuilderDataSource
{
IQueryable<Compeditor> Compeditors { get; }
IQueryable<Event_Class> Event_Classes { get; }
IQueryable<Event> Events { get; }
IQueryable<Class_Type> Class_Types { get; }
void Save();
}
}
You say your error is on this line (in your controller):
Compeditors.add(compeditor);
However, "Compeditors" is decalred in BodyBuilderDB (your _db field in your controller). So probably what you want is:
_db.Compeditors.add(compeditor);

Categories

Resources