Friends Don’t Let Friends Swallow NullReferenceException


Friends Don’t Let Friends Swallow NullReferenceException

If you are using ASP.NET MVC, Core or non-Core, chances are you are swallowing NullReferenceException without you even noticing.

You can see the screenshot of this repro in my previous post (see: Sixth, fixed null model)

How I Boosted 3.3 Minutes Slow ASP.NET MVC 5 Web App Startup to 3 Seconds
Yes, you’re h̸o̸l̸d̸i̸n̸g̸ ̸i̸t̸ ̸w̸r̸o̸n̸g̸ reading it right.

はい、読み間違いではない。

medium.com

But, let’s reproduce this using simple ASP.NET MVC Core program.
First, just create a normal MVC application. Then, add the following action:

public IActionResult Sample()
{
return View();
}

Also, add this new ModelView class.

public class PantsViewModel
{
public string FancyPants { get; set; }
}

Yeah, fancy pants ala Scott Hanselman. I’m a huge fan of his!!
He is amazing! Also, check this out:

I'm Scott Hanselman, ask me anything!
My name is Scott Hanselman. I'm a programmer, teacher, and speaker. I work in Open Source on ASP.NET and the Azure…dev.to

Oh, back to the topic…

Add a new View using Visual Studio dialog, use “Create” as Template, and then choose our newly created SampleViewModel as the Model class, like this:

Add MVC View

The result should be like this:

Our generated View file

Nothing special here. 
It’s just an ordinary View, without those shared layout applied, just for the sake of simplicity. Now press F5 and try to access the page.

View result

There is no exception. Of course.
Now turn on this setting in Visual Studio:

Enable capturing NullReferenceException

and also this one:

Disable ‘Just My Code’

Now, try to access the page again.

Exception Thrown

NullReferenceException occurred, but it’s swallowed by the framework silently. It is hidden away from us. Even your dog won’t notice it.
We all know that throwing exception is expensive…

Let’s dive into the source code.
Yes, you can see the ASP.NET MVC framework source code by enabling these options:

Enable source server and Source Link support

Restart the debugger by pressing Ctrl+Shift+F5.
Here we go.

ExpressionMetadataprovider.cs

Model accessor is trying to access a null container, guarded by catch NullReferenceException clause.

To avoid this hidden NullReferenceException, pass our PantsViewModel to the view, like so:

Pass our model to the view

Wonder what’s PVM? Notice Visual Studio highlights the PantsViewModel? Now I believe you got the idea. Pretty cool, heh? Don’t tell your Mom that I use it a lot.

After specifying our PantsViewModel explicitly, fire our lovely debugger again.

No more NullReferenceException

No more exception. We don’t really use the model in this case, but we avoid throwing and catching the exception that takes place behind the scenes. We save a few milliseconds CPU time, resulting in a slightly faster page load.

Quick Benchmark

I did a quick benchmark to see how bad it is to throw an exception. I used this super magnificent awesome splendid wonderful library:
http://benchmarkdotnet.org/

The result:

Throw NullReferenceException vs allocate new object

Obviously, we can see that the winner is DontThrowNRE, both in terms of execution speed and memory allocation that contribute to GC pressure.

So the question is, why the framework is swallowing NullReferenceException?

No null checking?

Why not null check here?

Is it by design? It’s been there for years since non-Core era. So there must be a reason behind this.

Summary

ASP.NET MVC framework is swallowing NullReferenceException without you even noticing. While it might slow the page load a little bit, it is not that significant. Instead of null, consider to pass your ViewModel object to the view to avoid this problem.

[Update: I asked this on https://github.com/aspnet/Mvc/issues/7378; it is scheduled to be fixed on 2.2.0 milestone]