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:
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.
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()));