Search code examples
c#asp.net-coreactive-directoryhangfire

Hangfire - Creating a new DirectorySearcher object with a DirectoryEntry as an argument throws NullReferenceException


I am trying to create a DirectorySearcher object using an existing DirectoryEntry object, but when I do it throws a System.NullReferenceException on that line. The following works in a standalone .NET 6.0 Console application, but not in a .Net 6.0 Console application that is doing work as a worker for a Hangfire Server. Here is the class and method that I get the exception with:

public class LocalADConnector : IADConnector
{
    public void GetUserADInfo(string username, string saGUID)
    {
        if (string.IsNullOrWhiteSpace(username)) { throw new ArgumentNullException(nameof(username), $"Argument {nameof(username)} of type {username.GetType()} may not be null or empty."); }    
        using (DirectoryEntry dirEntry = new DirectoryEntry(_adServer, _adUser, _adPass))
        {
            using (DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry)) //Exception is thrown here.
            {
                dirSearcher.Filter = $"(&(objectClass=user)(SAMAccountName={username}))";

                using (DirectoryEntry adUser = dirSearcher.FindOne().GetDirectoryEntry())
                {
                    if (adUser == null)
                    {
                        throw new ArgumentException($"User with the username {username} does not exist!");
                    }

                    foreach (string property in adUser.Properties.PropertyNames)
                    {
                        Console.WriteLine($"{property}: {adUser.Properties[property].Value}");
                    }
                }
            }
        }
    }
}

Here is the method that will get enqueued by Hangfire through the web project, and then executed by a Windows service:

public void UpdateUser(string employeeID, IHRConnector hrConnector, IADConnector adConnector, string saGUID)
{
    try
    {
        adConnector.GetUserADInfo(employeeID, saGUID);

        //There is other stuff here, but it's not relevant.
    }
    catch (Exception ex)
    {
        Log.Error(ex);
        throw;
    }
}

And here is the serialization settings for Hangfire:

builder.Services.AddHangfire(config =>
    config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseDefaultTypeSerializer()
    .UseSerializerSettings(new Newtonsoft.Json.JsonSerializerSettings
    {
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto
    })
    .UseSqlServerStorage($"{builder.Configuration.GetConnectionString("HangfireDB")}uid={Environment.GetEnvironmentVariable("LGN_HF_USR", EnvironmentVariableTarget.Machine)};pwd={Environment.GetEnvironmentVariable("LGN_HF_PWD", EnvironmentVariableTarget.Machine)}", new Hangfire.SqlServer.SqlServerStorageOptions { SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5) })
);

I have tried creating the objects and then applying the properties after, but the exception occurs at the

dirSearcher.SearchRoot = dirEntry;

line. Creating a DirectorySearcher object in the immediate window using dirEntry works just fine.

Thanks in advance.

UPDATE:

The NullReferenceException occurred on a different logging line when I tried creating a default DirectorySearcher, so I think the actual object that this method is in is getting cleaned up/set to null for some reason.

UPDATE 2:

I'm convinced this issue is coming from having an interface as one of the arguments for the method enqueued by Hangfire. I have updated the code above to show more of the problem.


Solution

  • This is embarrassing, but the issue was that I was debugging in Release and not Debug, so it wasn't giving me the correct line that the System.NullReferenceException was happening on. Specifically, the exception was from trying to get the value of an AD property that didn't exist. Thanks for everyone's help, and Bing Chat for pointing me in the right direction.