Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MulticastDelegate exception being thrown only in production environment

I have a very weird issue occurring only in production environment. The exception has the message

"Delegate to an instance method cannot have null 'this'".

The method where the exception is being thrown is very simple, and worked for a long time, so the problem must be an obscure dependency in the environment, or something like that...

I'm using ASP.NET Web API, hosted in Azure, and the action method of controller is executed via AJAX.

Here is the code where the exception was thrown:

public class BlacklistService : IBlacklistService
{
    public bool Verify(string blacklist, string message)
    {
        if (string.IsNullOrEmpty(blacklist)) return true;
        var split = blacklist.ToLower().Split(';'); // exception is thrown here
        return !split.Any(message.Contains);
    }
}

Here is the relevant part of stack trace:

at System.MulticastDelegate.ThrowNullThisInDelegateToInstance() 
at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr) 
at MyApp.Business.Services.BlacklistService.Verify(String blacklist, String message)
at MyApp.Business.Services.ContactMessageFactory.GetVerifiedStatus(String mensagem)
at MyApp.Business.Services.ContactMessageFactory.GetMailMessage(ContactForm contactForm)
at MyApp.Business.ContactEmailService.Send(ContactForm contactForm)

Someone can figure out the possible causes of this exception? Thanks in advance.

like image 775
Leonardo Lima da Silva Avatar asked Mar 14 '23 18:03

Leonardo Lima da Silva


1 Answers

The problem lays with the fact that message is actually null. You can reproduce this quite easily:

void Main()
{
    Verify("hello", null);
}

public bool Verify(string blacklist, string message)
{
    if (string.IsNullOrEmpty(blacklist)) return true;
    var split = blacklist.ToLower().Split(';'); // exception is thrown here
    return !split.Any(message.Contains);
}

What happens is that message.Contains is passed to Func<string, bool> constructor via the method group conversion, it looks like this:

Func<string, bool> func = ((string)null).Contains;
return !split.Any(func);

And that is what causes MulticastDelegate to go bananas. You can also see that in the generated IL:

IL_0028:  ldftn       System.String.Contains
IL_002E:  newobj      System.Func<System.String,System.Boolean>..ctor
IL_0033:  call        System.Linq.Enumerable.Any

In order for this not to happen, make sure you null check message as well:

public bool Verify(string blacklist, string message)
{
    if (string.IsNullOrEmpty(blacklist)) return true;
    if (string.IsNullOrEmpty(message)) return false;

    var split = blacklist.ToLower().Split(';'); // exception is thrown here
    return !split.Any(message.Contains);
}
like image 186
Yuval Itzchakov Avatar answered Apr 07 '23 01:04

Yuval Itzchakov