3

I am attempting to run awaited Async connections to a remote webservice. The URL is configurable, and if it is invalid, I am getting a Null Reference exception that ignores Try/Catch blocks and crashes the entire IIS Worker Process.

public static void SendMessage(FileInfo FileToSend, string RecipientName, string RecipientNumber){
{
    //Connection Info retrieved from DB
    string url = "http://NotARealUrl.com/";
    string username = "NotARealUN";
    string password = "NotARealPW";

    //not Awaiting this because all logging in event of job failure is handled by the job itself. There is no reason to wait for completion
    Send (FileToSend, url, username, password, RecipientName, RecipientNumber)
}

public static async Task Send(FileInfo FileToSend, string url, string username, string password, string sentByID, string faxRecipient, string faxNumber)
{
    var handler = new HttpClientHandler
    {
        Credentials = new NetworkCredential(username, password), 
        PreAuthenticate = true
    };

    var client = new HttpClient(handler);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    try
    {
        var response = await client.GetAsync(url); //Exception is throw when I step past this point
        response.EnsureSuccessStatusCode();

        var contentAsString = await response.Content.ReadAsStringAsync();
        var root = JsonConvert.DeserializeObject<FaxingAPIRoot>(contentAsString);

        //Code continues, using 'root' in order to send the message in accordance with the Faxing API I'm using
    }
    catch (Exception e)
    {
        //Graceful Error Handling 
    }
}

At the line indicated above...

var response = await client.GetAsync(url);

The code throws the following exception, which bypasses the Catch block and immediately crashes the host process, whether that be Visual Studio's IIS Express, or the IIS Worker Process.

An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll

Additional information: Object reference not set to an instance of an object.

With a Callstack of...

    mscorlib.dll!System.Threading.Tasks.AwaitTaskContinuation.ThrowAsyncIfNecessary.AnonymousMethod__18_0(object s) 
    mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state)  
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   
    mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()  
    mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()    
    mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() 
    [Native to Managed Transition]  

I have verified that the URL being passed in is not null and the HttpClient is not null. Is there a way to force this exception to be caught or, barring that, to preempt the error by checking the validity of that URL before it attempts to call it?

guildsbounty
  • 3,326
  • 3
  • 22
  • 34
  • 1
    What’s the calling code of your GetAsync part? The error looks like you don’t await at some point. Check your entire calling chain for this. – ckuri Feb 16 '18 at 21:51
  • @ckuri There is definitely a point where I'm not Awaiting. But all error handling and error logging is internal to the awaited section. I'm trying to trigger this as a Fire and Forget function overall. I'll expand the code section to show how I'm doing this (maybe I'm doing it wrong) – guildsbounty Feb 16 '18 at 21:56
  • @abatishchev No, I don't. The comment above it explains why. That is intended to be a Fire and Forget method. I may be handling that incorrectly, but I do not want to await that methods completion...just kick it off and move on. – guildsbounty Feb 16 '18 at 22:16
  • 1
    Then see https://stackoverflow.com/questions/5613951/simplest-way-to-do-a-fire-and-forget-method-in-c-sharp-4-0 – abatishchev Feb 16 '18 at 22:17
  • 1
    okay...that apparently fixed it. Now....can anyone offer any insight into _why_ that fixed the problem? – guildsbounty Feb 16 '18 at 22:26
  • I guess your catch throws an exception which becomes unobserved and thus is rethrown when the task gets recycled or disposed. If you access the tasks Exception property, either directly or indirectly (await, Wait() or Result), it becomes an observed exception and thus gets swallowed. I don’t which of the links solutions you took, but the simplest way for this would be `Send(…).ContinueWith(t => { var ex = t.Exception }, TaskContinuationOptions.OnlyOnFaulted)`. – ckuri Feb 16 '18 at 22:45
  • @ckuri but the exception is not unobserved, OP has a try catch in the code that should catch it. – Dave Feb 17 '18 at 08:17
  • @Dave That’s why I guess the exception is thrown inside his catch block. – ckuri Feb 17 '18 at 08:25
  • @ckuri sorry I missed where you'd said that, yes that makes a bit more sense. – Dave Feb 17 '18 at 08:32
  • @ckuri I do not throw an exception inside the catch block, and even if I did, walking through there while debugging would have stepped into the catch block. The catch block logs the error, then exits the attempt to send the fax. This works smoothly with every other exception I can make this function throw. Instead, while debugging, I 'Step Over' or 'Step Into' the line of code I cited, and the entire IIS process immediately crashes with a NullRef exception. – guildsbounty Feb 17 '18 at 14:22
  • @Igor I'm going to have to disagree that this is a duplicate. I am not asking how to 'properly' set off a Fire and Forget task. The solution 'Properly set off the Fire and Forget Task' is the same, but the problem is distinct. I am getting an uncatchable exception being thrown, and I feel it would be profitable to the stack and future seekers for this question to provide an explanation as to _why_ this is happening. – guildsbounty Feb 17 '18 at 14:26

0 Answers0