30 Jul 2015
Quite often people stumble into same problems again and again, and getting a NullReferenceException is the one that occurs most frequently, and frankly, can be quite annoying. This problem happens when writing brand-new ASP.NET MVC code, such as controllers or views, but also when modifying existing code that used to work just fine, but somehow suddenly got broken. Here I want to show you why these exceptions happen and how to fix them, so you can stop wasting your time and do more of the programming that you actually enjoy.
Not sure where should those try
…catch
blocks go in your code? Learn how to deal with various
types of exceptions in your apps: Where should you put “try … catch” statements in your C#
code
NullReferenceException is exactly what it says - it is thrown by .NET Runtime when your code tries to access properties or call methods using empty, or null, reference. It sounds obvious and trite, but finding a place in your code where things went haywire may take some time.
Let’s say you have a UserProfile.cshtml page that displays “Industry” selection drop down list for a logged in user (to put a dropdown on a form see my other article):
@model UserProfileModel
<div class="form-group">
@Html.LabelFor(m => m.Industry)
@Html.EnumDropDownListFor(model => model.Industry,
Model.Industries,
"- Please select your industry -",
new { @class = "form-control" })
</div>
and when you hit this page you see the following exception:
|
|
Believe me or not, this problem trips people over most often. The reason for this exception is that no model is being passed to the view from the controller’s action:
public ActionResult UserProfile() {
var userModel = GetLoggedInUser();
//
// … some more super-serious business logic in here ...
//
return View(); // <-- HERE'S THE PROBLEM!
}
That’s why when the view is being rendered, Model
variable inside of .cshtml
points to null
, and trying to access null.FirstName
obviously throws a brand
spanking new NullReferenceException
. To fix this need to pass an instance of
the model to the View() call:
public ActionResult UserProfile() {
var userModel = GetLoggedInUser();
//
// … some more super-serious business logic in here ...
//
return View(userModel); // <-- JUST PASS THE MODEL HERE, TOO EASY!
}
This is a second most-common problem - when loading entities from a database,
you cannot always be sure whether an object you’re trying to load or one of its
linked entities exists. Say there’s an optional Address
object that
UserProfile
object can be linked to. If you do the following in your code,
you’ll get a NullReferenceException when Address
is missing:
public int GetUserPostCode(int userId) {
var user = GetUserFromDb(userId);
return user.Address.PostCode;
}
In which case the following exception will blow your call stack right up:
|
|
To fix this exception, you need to retrieve data in a safe manner - by checking all the reference types first and avoiding dangerous assumptions that related objects are always going to be present:
public int? GetUserPostCode(int userId) { // Notice that function returns nullable int now
var user = GetUserFromDb(userId);
if (user != null && user.Address != null) { // This check will help to avoid NullReferenceExceptions
return user.Address.PostCode;
}
return null;
}
Similarly, calling any functions on a null reference will result in NullReferenceException. Say you are building an auction site, where users can add photos to their listings. There’s class called ‘Listing’ that has a collection of ‘Photos’, and you want users to be able to submit new listings along with the photos in the following manner:
[HttpPost]
public ActionResult NewListing(ListingModel model) {
var newListing = new ListingDBObject {
Price = model.Price,
Title = model.Title,
ContactNumber = model.ContactNumber
}
foreach (var photo in model.Photos) {
newUser.Photos.Add(new PhotoDBObject { // <- THIS WILL BLOW UP!
BinaryData = photo.Data;
});
}
//...here goes code that saves new listing to the database
}
Again, you’ll get a brand new NullReferenceException with the following stack trace:
|
|
To fix this you need to initialise the collection first:
[HttpPost]
public ActionResult NewListing(ListingModel model) {
var newListing = new ListingDBObject {
Price = model.Price,
Title = model.Title,
ContactNumber = model.ContactNumber
}
newUser.Photos = new List<PhotoDBObject>(); // Initialise the collection first so it's not null
foreach (var photo in model.Photos) {
newUser.Photos.Add(new PhotoDBObject { // Add objects to the collection
BinaryData = photo.Data;
});
}
//...here goes code that saves new listing to the database
}
I hope this article helped you to solve your problem and saved you a bit of time and frustration!
Don’t miss my next post - subscribe to the mailing list to get handy tips and solutions for ASP.NET NVC Core. I never spam, and you can unsubscribe at any time.