Object Reference Not Set to and Instance of an Object Error?

Superfreak3

Member
Joined
Oct 10, 2019
Messages
5
Programming Experience
3-5
Hi all,
I'm getting the object reference not set to an instance of an object error in teh following code...
C#:
private void AddRewriteRule(string port, string avPort, string ruleName, string ruleUrlMatch)
{
    using (ServerManager serverManager = new ServerManager())
    {
        Site site = serverManager.Sites.FirstOrDefault(s => s.Bindings.ElementAt(0).EndPoint.Port == Int32.Parse(port));
        string siteName = site.Name;

I think its blowing up at the highlighted code and may have something to do with Int32.Parse. ??
I had a troubleshooting message right after that code and it never reached it. The port is coming into the function as a string, as you can see.
Any idea what is wrong here? This is code from a widget where we haven't seen this issue yet so it was working. Scratching my head.
Any help or points to what else I could look at/for would be greatly appreciated!!

THANKS!!!!
 
Last edited by a moderator:
Did this occur while debugging or in deployed code? If the former, the debugger will tell you exactly what line the exception was thrown on. If the latter, you should be logging exceptions and the stack trace will tell you what line was at issue too, if you deployed the PDB file too.

A NullReferenceException occurs when you try to access a member of an object via a variable (or other reference, e.g. function result) that is null. The Int32.Parse call can't be the issue because there's no reference there to be null.

There is an obvious issue with your code though. You call FirstOrDefault and then you just go ahead and use the result. The whole point of FirstOrDefault is that it might return null. What is most likely happening is that it is indeed returning null, because there are no matching items, and the exception occurs when you try to get the Name of an object that doesn't exist.

Firstly, you need to make sure that you are calling the correct method. The First, FirstOrDefault, Single and SingleOrDefault methods are all similar but there is never* a situation where more than one is appropriate. If there might be more than one match but you only the first, you call First or FirstOrDefault, otherwise you call Single or SingleOrDefault. If there might be no matches then you call FirstOrDefault or SingleOrDefault, otherwise you call First or Single. In short:

First1 or more matches
FirstOrDefault0, 1 or more matches
Single1 match
SingleOrDefault0 or 1 match

If you call First or Single then you know that the result will be an object, because an exception would have been thrown if there was no match. If you call FirstOrDefault or SingleOrDefault then the result may be null, so you have to allow for that in subsequent code. You would do that by either checking for null explicitly, e.g.

C#:
Site site = serverManager.Sites.FirstOrDefault(s => s.Bindings.ElementAt(0).EndPoint.Port == Int32.Parse(port));
string siteName = null;

if (site != null)
{
    siteName = site.Name;
}

or using null propagation, e.g.

C#:
Site site = serverManager.Sites.FirstOrDefault(s => s.Bindings.ElementAt(0).EndPoint.Port == Int32.Parse(port));
string siteName = site?.Name;

In both those examples, siteName would end up being null if there was no match. As you can see, null propagation is far more succinct, so you should use it if it's appropriate.

Basically, it looks to me most likely that you just don't have a site with that port number. The truth of that is easy to determine with proper debugging.
 
WOW! Thanks so much for that explanation!! I will look through it today and let you know.

The issue never occurred in-house during QA, but only in this instance at a customer site.

For more context here is what is happening. During our web app installation, a port is passed to this utility. The port currently defaults to 80 or the default website. IIS is a prerequisite so for the most part the site should be there and bound to port 80.

Also during install the settings passed are written to a config file for information load if the same utility is launched from a shortcut for post install configuration.

I have to look at all of the options you provided to see which code would be best to use in my case, but I would think there should be at least one and only one site for port 80. There is either something wrong in IIS or the config file is screwed up in some way. I'll have to troubleshoot the values pulled from the file and check on IIS. When we checked yesterday, the Default Web Site points to 80 on this user's server.
 
Last edited:
OK, again, thank you so much for that detailed explanation of options.

I whipped up a little app which includes just this code to display the name of a site after entering the port number. Using FirstOrDefault and entering port 80, all is good and the Default Web Site is displayed.

I then entered port 81 and got the 'Object reference not set to an instance of an object.' error. So, I switched to using First instead and after entering the port with no site, I get 'Sequence contains no matching element.' That one seems a little more appropriate.

However, I guess you can have multiple websites on a single port using host headers, so I'm not sure which is best to use. I'll have to check with Dev to see if a requirement of our app is to have the site under which our app is installed to be the only site bound to a particular port, in this case 80 (for now).
 
If there being no matches is a reasonable scenario then use FirstOrDefault and then test for null. Then neither of those exceptions can be thrown.

That's the thing. I would think that there would be at least one hit, and based on the customer's machine I would think the code should be OK, or at least functioning as is.

How should I check for null? Wrap in try catch and examine exception or if (<find site on port number> !null)?

If there is no site found on the port coming into the function, I could raise a custom exception indicating no site found on that port. That would probably help our deployment folks in the field. If no site found on the port, I could display that information/custom exception and then just exit.
 
If there being no match is an exceptional situation, i.e. should not happen under normal operation, then throwing an exception is perfectly acceptable and quite possibly the best option.
 
Excellent, thank you for all the help and information. The quick responses were much appreciated too!!

Another quick question, and I don't know if this is off topic, but from the code above, which attempts to get the site by port, how does that actually work. Does it try to communicate somehow on that port or does it just query site attributes and finds the port from a config file or the like?

The reason I ask is I threw a custom exception on the users system to troubleshoot and it doesn't seem like that code is seeing the port. I'm just trying to decipher how that can be possible. When we look in IIS on their system, there is binding for port 80 on the site.

I should say, we did notice some weirdness on their system yesterday. We noticed that the web.config file was gone from inetpub\wwwroot so something may be amiss with IIS in general on this system. It just may have exposed an area for better error handling on my part.
 
I don't know exactly what serverManager is but I can tell you that there's no communication going on. The code enumerates the items in the serverManager.Sites collection and, for each one, examines the first item in its Bindings collection. It looks at the EndPoint property of that object and the Port property of that. That is just reading the existing configuration information, not trying to use it to communicate.
 
I recommend changing this:
C#:
Site site = serverManager.Sites.FirstOrDefault(s => s.Bindings.ElementAt(0).EndPoint.Port == Int32.Parse(port));
string siteName = site.Name;

To:
C#:
if (!int32.TryParse(port, out int32 portNumber))
    throw new FormatException("Port number could not be parsed");

Site site = serverManager.Sites.FirstOrDefault(s => s.Bindings.Any(b => b.EndPoint.Port == portNumber));
if (site == null)
    throw new InvalidOperationException($"No site with binding to port {portNumber} found.");

string siteName = site.Name;
 
Back
Top Bottom