Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

ServiceStack IAppSettings was not ready and would result NULL reference exception if used in constructor

It seems like the IAppSettings implementation was not ready from IoC in the constructor.

Before I go into details, I’ve read similar problems:

Both were answered by @mythz that he was not able to reproduce it.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

From the Doc

"ServiceStack made AppSettings a first-class property, which defaults to looking at .NET’s App/Web.config’s.": https://docs.servicestack.net/appsettings#first-class-appsettings

And there is default IoC registration already in Funq to give you AppSettings when you ask for IAppSettings:

enter image description here

What I have

All my codes are in the repo: https://github.com/davidliang2008/MvcWithServiceStack

The demo app is just an ASP.NET MVC app (.NET 4.8) that built using the template, the simplest you can get, with ServiceStack (5.12.0) installed:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ...
        new AppHost().Init();
    }
}

public class AppHost : AppHostBase
{
    public AppHost() : base("MvcWithServiceStack", typeof(ServiceBase).Assembly) { }

    public override void Configure(Container container)
    {
        SetConfig(new HostConfig
        {
            HandlerFactoryPath = "api";
        }

        ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
    }
}

Then I have a base class for the ServiceStack Service, and a HelloService just to demo:

public abstract class ServiceBase : Service { }

public class HelloService : ServiceBase
{
    public IAppSettings AppSettings { get; set; }

    public object Get(HelloRequest request)
    {
        return new HelloResponse
        {
            Result = $"Hello, { request.Name }! Your custom value is { AppSettings.Get<string>("custom") }."
        };
    }
}

[Route("/hello/{name}")]
public class HelloRequest : IReturn<HelloResponse>
{
    public string Name { get; set; }
}

public class HelloResponse
{
    public string Result { get; set; }
}

What works

When you’re not using IAppSettings in the constructor, whether in the HelloService or its base class ServiceBase, everything works out fine.

When you clone the project to your local, if you navigate to /api/hello/{your-name}, you will see its response would be able to get the custom value from web.config:

// TODO: attach screenshot

What doesn’t work

When you’re trying to get the IAppSettings and initialize something else with some app setting values in the constructor – whether it’s in the child class or the base class, IAppSettings will fail to get the implementation from IoC, and result a NULL reference exception:

public abstract class ServiceBase : Service
{
    public IAppSettings AppSettings { get; set; }

    public ServiceBase()
    {
        // AppSettings would be NULL
        var test = AppSettings.Get<string>("custom");
    }
}

OR

public class HelloService : ServiceBase
{
    public HelloService()
    {
        // AppSettings would be NULL
        var test = AppSettings.Get<string>("custom");
    }
}

// TODO: attach screenshots

>Solution :

You cannot use any property dependency in the constructor since the properties can only be injected after the class is created and the constructor is run.

You’ll only be able to access it in the Constructor by using constructor injection, e.g:

public class HelloService : ServiceBase
{
    public HelloService(IAppSettings appSettings)
    {
        var test = appSettings.Get<string>("custom");
    }
}

Or accessing the dependency via the singleton:

public class HelloService : ServiceBase
{
    public HelloService()
    {
        var test = HostContext.AppSettings.Get<string>("custom");
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading