12

I'm close to giving up on this mvc app for today!!

I'm following the Mvc Music Store Tutorial and I'm stuck on page 54.

this is the error I'm getting:

System.NullReferenceException: Object reference not set to an instance of an object.

The error occurs in the third paragraph block (dropdownlist) in the following code:

<%@ Import Namespace ="MvcMovies1" %>
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcMovies1.Models.Album>" %>

<p>
    <%: Html.LabelFor(model => model.Title) %>
    <%: Html.TextAreaFor(model => model.Title) %>
    <%: Html.ValidationMessageFor(model => model.Title) %>
</p>

<p>
    <%: Html.LabelFor(model => model.Price) %>
    <%: Html.TextAreaFor(model => model.Price) %>
    <%: Html.ValidationMessageFor(model => model.Price) %>
</p>

<p>
    <%: Html.LabelFor(model => model.AlbumArtUrl) %>
    <%: Html.TextAreaFor(model => model.AlbumArtUrl) %>
    <%: Html.ValidationMessageFor(model => model.AlbumArtUrl) %>
</p>

<p>
    <%: Html.LabelFor(model => model.Artist) %>
    <%: Html.DropDownList("ArtistId", new SelectList(ViewData["Artists"] as IEnumerable, "ArtistId", "Name", Model.ArtistId)) %>
</p>

<p>
    <%: Html.LabelFor(model => model.Genre) %>
    <%: Html.DropDownList("GenreId", new SelectList(ViewData["Genres"] as IEnumerable, "GenreId", "Name", Model.GenreId)) %>
</p>

    <div>
        <%: Html.ActionLink("Back to List", "Index") %>
    </div>

This ascx file is contained within an Edit.aspx file:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcMovies1.ViewModels.StoreManagerViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<form id="form1" runat="server">
    <h2>Edit</h2>
    <% using (Html.BeginForm())
       { %>
      <%: Html.ValidationSummary(true)%>

    <fieldset>
      <legend>Edit Album</legend>
      <%: Html.EditorFor(model => model.Album,
          new { Artists = Model.Artists, Genres = Model.Genres }) %>

          <p><input type="submit" value="Save" /></p>


    </fieldset>

      <% } %>
      </form>
</asp:Content>

I realise there's a lot of code there but if anyone can see something obvious that I am doing wrong I'd be very grateful.

EDIT

StoreManagerController.cs (Edit)

 public ActionResult Edit(int id)
    {
        var viewModel = new StoreManagerViewModel
        {
            Album = storeDB.Albums.SingleOrDefault(a => a.AlbumId == id),
            Genres = storeDB.Genres.ToList(),
            Artists = storeDB.Artists.ToList()
        };

        return View(viewModel);
    }

Andddd..StoreManagerViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MvcMovies1.Models;

namespace MvcMovies1.ViewModels
{
    public class StoreManagerViewModel
    {
        public Album Album { get; set; }
        public List<Artist> Artists { get; set; }
        public List<Genre> Genres { get; set; }
    }
}

Again I realise i called it MvcMovies1, this was a typo but everything is marked up accordingly.

4
  • 4
    Can you post your action in your controller as well. Are you setting ViewData["Artists"] in the controller? Commented Oct 20, 2010 at 15:53
  • Hi Simon G. I have posted the requested code. Thanks for the reply. Commented Oct 20, 2010 at 15:59
  • Can you put a breakpoint on that line and check all the properties for nulls? Commented Oct 20, 2010 at 16:10
  • Possible duplicate of What is a NullReferenceException, and how do I fix it? Commented Jan 11, 2017 at 10:27

6 Answers 6

9

Does Album have an ArtistId since in that line you are calling Model.ArtistId and if Album doesn't have that property on it you will get a null reference exception. That's because the Model is a shorthand for the object that is strongly typed to your view, which happens to be Album in your case.

There is no where in your above code where you are setting the ViewData["Artists"]. Are you setting that anywhere since that could be your issue too.

EDIT

Set the ViewData in the action and it should work:

public ActionResult Edit(int id)
{
     var viewModel = new StoreManagerViewModel
     {
         Album = storeDB.Albums.SingleOrDefault(a => a.AlbumId == id),
         Genres = storeDB.Genres.ToList(),
         Artists = storeDB.Artists.ToList()
     };

     ViewData["Artists"] = storeDB.Artists.ToList();
     ViewData["Genres"] = storeDB.Genres.ToList();

     return View(viewModel);
 }
Sign up to request clarification or add additional context in comments.

6 Comments

But since the model is strongly typed wouldn't the page not compile if ArtistId was missing rather than throw a null reference exception?
Hi amurra...I think it's the ViewData["Artists"] this is my issue. I'm only learning Mvc so I have literally followed what was on the tutorial so I'm stumped!
@Rup - I believe only if you are compiling the views will it show up then, otherwise it would be found during runtime
@amurra..thanks for the post. Just tried it there but still the same error in the same place. I suppose that's something eliminated all the same.
@amurra Yes, it'd be at runtime when you try to load the page but it would still be a compile error ("Model does not have property AlbumId" or similar) not a null reference exception.
|
7

First you need to add properties in your view model to hold selected artist and selected genre:

public class StoreManagerViewModel
{
    public Album Album { get; set; }
    public int? SelectedArtistId { get; set; }
    public List<Artist> Artists { get; set; }
    public int? SelectedGenreId { get; set; }
    public List<Genre> Genres { get; set; }
}

Then in your Edit.aspx view instead of:

<%: Html.EditorFor(model => model.Album,
    new { Artists = Model.Artists, Genres = Model.Genres }) %>

You could simply:

<%: Html.EditorForModel() %>

and in your editor template ~/Views/Home/EditorTemplates/Album.ascx:

<%@ Import Namespace ="MvcMovies1" %>
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcMovies1.Models.Album>" %>

<p>
    <%: Html.LabelFor(model => model.Title) %>
    <%: Html.TextAreaFor(model => model.Title) %>
    <%: Html.ValidationMessageFor(model => model.Title) %>
</p>

<p>
    <%: Html.LabelFor(model => model.Price) %>
    <%: Html.TextAreaFor(model => model.Price) %>
    <%: Html.ValidationMessageFor(model => model.Price) %>
</p>

<p>
    <%: Html.LabelFor(model => model.AlbumArtUrl) %>
    <%: Html.TextAreaFor(model => model.AlbumArtUrl) %>
    <%: Html.ValidationMessageFor(model => model.AlbumArtUrl) %>
</p>

and in your editor template ~/Views/Home/EditorTemplates/StoreManagerViewModel:

<%@ Import Namespace ="MvcMovies1" %>
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcMovies1.ViewModels.StoreManagerViewModel>" %>

<%: Html.EditorFor(model => model.Album) %>

<p>
    <%: Html.LabelFor(model => model.SelectedArtistId) %>
    <%: Html.DropDownListFor(model => model.SelectedArtistId, new SelectList(Model.Artists, "ArtistId", "Name")) %>
</p>

<p>
    <%: Html.LabelFor(model => model.SelectedGenreId) %>
    <%: Html.DropDownListFor(model => model.SelectedGenreId, new SelectList(Model.Genres, "GenreId", "Name")) %>
</p>

<div>
    <%: Html.ActionLink("Back to List", "Index") %>
</div>

4 Comments

Hi Darin, you seem to know your stuff but one thing I don't understand is why the Album.ascx file is now broken down into two different files?
Because for better separation of concerns the Album editor template should only care about album properties and not Genres and Artists which are dissociated. It also avoids you working with ugly ViewState and magic strings and casting to IEnumerable, it is always preferable to work with strong typing.
Hmm, okay. In the tutorial you see the html textboxes, labels, dropdownlists, etc are all in the one file. I'd like to follow that as closely as I can. If I were to merge the above two into one, would that be okay to work with?
@TaraWalsh, for me it's totally unacceptable to use ViewData and perform type casts in a view. So you can do whatever you want, I just gave my two cents.
2

Have you tried casting to List and List instead of IEnumerable?

Comments

2

problem:

Object reference not set to an instance of an object

Solution:

pubblic ActionResult yourDetails()
{
     List<YourEntityName> PropertyName= new List<YourEntityName>();
     list = db.PropertyName.ToList();
     return View(list);
}

YourEntityName Mean your Table Name i.e PassengerDetial

PropertyName Mean your Class pubblic property i.e PassengerDetails

pubblic Class PassengerDetailContext : DbContext 
{
  pubblic DbSet<PassengerDetail>  passegerDetails {get;set;}
}

List<PassengerDetail> passegerDetails = new List<PassengerDetail>();
list = db.passegerDetails.ToList();
return View(list);

Comments

2

You are simply not setting ViewData["Artists"] and ViewData["genres"] as I can see from your action method.

Make sure you are setting these values somewhere during lifetime of a request if you want to use them in your view.

3 Comments

Isn't it merged into the ViewData by the EditorFor call? She's passing it in the additionalViewData parameter msdn.microsoft.com/en-us/library/ff406462.aspx
please spell 'you' instead of 'u'. this is not twitter.
@automagic var u = "you";
0

Had the same error while trying to run migration (update-database). had 2 projects namely ViewProject and DBcontextProject.

my problem was that I made ViewProject a start-up project and ran migration on DBcontextProject.

The solution was to make DBcontextProject a start-up project and run migration on DBcontextProject.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.