HttpContextAccessor.HttpContext is null on Linux while non-null on Windows in ServiceStack.Core

Viewed 1441

I have a simple ServiceStack project that runs on .NET Core 2.0. This works fine on Windows but fails on Linux. With the very same code (see below).

The service gets injected with an IHttpContextAccessor which is always non-null (Win & Linux) but its property HttpContext is always null on Linux and always non-null on Windows.

Minimal project to reproduce the issue:

using Funq;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using ServiceStack;

namespace TestSS
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services) { }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();
            app.UseServiceStack(new AppHost());
        }
    }

    public class AppHost : AppHostBase
    {
        public AppHost() : base("AO", typeof(InfoService).Assembly) { }

        public override void Configure(Container container)
        {
            var httpContextAccessor = new HttpContextAccessor();
            container.Register<IHttpContextAccessor>(httpContextAccessor);
        }
    }

    public class InfoService : Service
    {
        [Route("/info")] public class InfoRequest { }

        private readonly IHttpContextAccessor _accessor;

        public InfoService(IHttpContextAccessor accessor)
        {
            _accessor = accessor;
        }

        public object Any(InfoRequest request)
        {
            return $"Accessor: {_accessor};\nContext: {_accessor.HttpContext};";
        }
    }
}

Regarding how the project is run on Linux: No reverse-proxy (nginx etc), just dotnet build followed by dotnet run, accessed locally. Nothing fancy, nothing convoluted IMHO.


Win: Windows 10 Enterprise

Linux: Ubuntu 16.04 LTS

dotnet --version: 2.0.2 (both platforms)


Further investigation:

Commenting the IHttpContextAccessor registration in the AppHost.Configure method has a strange effect: On Windows nothing changes, everything works as expected, on Linux an exception is thrown because the dependency cannot be fulfilled.


Has anyone a solution, workaround, any information?

1 Answers

This is quite strange (to me), but it seems the fix is how you register the IHttpContextAccessor. This doesn't mean it is definitely the core of the issue but at least I got things working.

It certainly is a problem that the very same code, down to the last character, is behaving different on two platforms.

So the fix is to delete the two lines in the AppHost.Configure:

var httpContextAccessor = new HttpContextAccessor();
container.Register<IHttpContextAccessor>(httpContextAccessor);

and to register the IHttpContextAccessor in the Startup.ConfigureServices method:

services.AddSingleton<IHttpContextAccessor>(new HttpContextAccessor());

... and this fixes my issue.

If you need, like me, to have the instance of the HttpContextAccessor in the AppHost.Configure method you can retrieve the instance in the Startup.Configure method and inject it, via constructor, into the AppHost instance. The retrieval is done like so:

var httpContextAccessor = (IHttpContextAccessor)app.ApplicationServices.GetService(typeof(IHttpContextAccessor));

All in all, this is strange and it there must be some kind of bug somewhere since I can get away with not registering it on Windows but not on Linux.

Related