Search code examples
servicestackmessaging

ServiceStack Messaging API: Using HostContet.AppHost.ExecuteMessage in OnAfterInit gives NullReferenceException


As previously discussed here, I am sometimes using this approach to execute Services internally:

IMessage theMessage = new Message<Startup>(new Startup());
var reply = HostContext.AppHost.ExecuteMessage(theMessage); // The way to get the pipeline to execute when we do internal call, and get DI to work etc

This works well and as expected, except in one case: when I call this from the OnAfterInit method, that I override.

The idea is that I want to do some startup-stuff when the AppHost is ready, after initialization, but when doing this, it fails with a NullReferenceException:

public override void OnAfterInit()
{
    base.OnAfterInit();

    IMessage theMessage = new Message<Startup>(new Startup());
    var reply = HostContext.AppHost.ExecuteMessage(theMessage); 
}

Error:

enter image description here

   at ServiceStack.ServiceStackHost.<ApplyRequestConvertersAsync>d__361.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 45
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at ServiceStack.Host.ServiceController.ExecuteMessage(IMessage dto, IRequest req) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ServiceController.cs:line 584
   at ServiceStack.ServiceStackHost.ExecuteMessage(IMessage mqMessage) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.cs:line 1486
   at Test.Test.OnAfterInit() in C:\Git\Test\Test.cs:line 59

It seems that not all is initialized and ready. If I do this, it works:

public override void OnAfterInit()
{
    base.OnAfterInit();
    System.Threading.Timer t = new System.Threading.Timer((o) => 
    {
        IMessage theMessage = new Message<Startup>(new Startup());
        var reply = HostContext.AppHost.ExecuteMessage(theMessage);
    }, null, 100, int.MaxValue);
}

I would appreciate to know if I am missing something, and if there is a nicer way to resolve this. The Timer-thing works, but it doesn't sit right with me.


Solution

  • Executing Services should ideally be done at runtime not on Startup but if you do want to Execute Services you'll need to execute them at the very end of Startup when the rest of ServiceStack has initialized like in an AfterInitCallbacks, e.g:

    AfterInitCallbacks.Add(host => 
        host.ExecuteMessage(new Message<Startup>(new Startup()));