仅在生产环境中抛出MulticastDelegate异常

时间:2015-09-15 18:30:22

标签: c# asp.net-mvc azure string-split multicastdelegate

我有一个非常奇怪的问题,只发生在生产环境中。 该例外有消息

  

"委托实例方法不能为空''"。

抛出异常的方法非常简单,并且工作了很长时间,所以 问题必须是环境中的模糊依赖,或类似的东西......

我使用Azure中托管的ASP.NET Web API,控制器的操作方法是通过AJAX执行的。

以下是引发异常的代码:

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);
    }
}

以下是堆栈跟踪的相关部分:

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)

有人可以找出导致此异常的可能原因吗?提前谢谢。

3 个答案:

答案 0 :(得分:4)

问题在于message实际上是null。你可以很容易地重现这个:

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);
}

通过方法组转换将message.Contains传递给Func<string, bool>构造函数会发生什么情况,它看起来像这样:

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

这就是导致MulticastDelegate去香蕉的原因。您还可以在生成的IL中看到:

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

为了不发生这种情况,请确保您也检查以下消息:

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);
}

答案 1 :(得分:2)

具有空this的委托是用于结尾的方法string.Contains(),它使用您的message变量作为this指针。换句话说,在message为空的情况下进行了调用。

答案 2 :(得分:1)

消息为空时

失败。可以用这个

return !split.Any(part => (message != null && message.Contains(part)));