Topshelf: Issues using NancyFX with Topshelf 4.2.1

65 Views Asked by At

I am trying to develop a data access service using Visual Studio 2019, .Net Core 3.0. I am using NancyFX to handle http requests. this is working just fine as a console application. When I build and run, then in browser go to HTTP://localhost/, it returns the proper data. I have a working Nancy module to handle requests. Here is original Main code:

static void Main(string[] args)
{
    Logger.LogInfo("NancyDataService starting...");

    var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
    var hostConfig = new HostConfiguration();
    hostConfig.UrlReservations.CreateAutomatically = true;
    hostConfig.RewriteLocalhost = false;

    using (var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig))
    {
        try
        {
            nancyHost.Start();
            Console.WriteLine($"Nancy now listening on {uri}.\n\nPress any key to exit");
            Logger.LogInfo($"Nancy now listening on {uri}...");
        }
        catch (Exception ex)
        {
            Logger.LogError(ex.Message);
            Console.WriteLine("Error " + ex.Message + "\n\nPress any key to exit");
        }
        Console.ReadKey();
        Logger.LogInfo("NancyDataService stopped...");
    }
}

Now I want to make it a Windows Service. First try is with Topshelf. The following Main code is basically taken from Topshelf documentation and other articles about Topshelf.

static void Main(string[] args)
{
    Logger.LogInfo("NancyDataService starting...");
    var rc = HostFactory.Run(x =>
    {
        x.Service<DataService>(s =>
        {
            s.ConstructUsing(name => new DataService());
            s.WhenStarted(tc => tc.Start());
            s.WhenStopped(tc => tc.Stop());
        });

        x.RunAsLocalSystem();
        x.StartAutomatically();
        x.EnableServiceRecovery(r => r.RestartService(TimeSpan.FromSeconds(10)));
        x.SetServiceName("NancyDataService");
    });
    var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());  //11
    Environment.ExitCode = exitCode;
}

Here is my DataService class, basically built from the Topshelf docs and a couple of articles I found:

class DataService
{

    public DataService()
    {
    }

    private SemaphoreSlim _semaphoreToRequestStop;
    private Thread _thread;

    public void Start()
    {
        
        // start Nancy here
        var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
        var hostConfig = new HostConfiguration();
        hostConfig.UrlReservations.CreateAutomatically = true;
        hostConfig.RewriteLocalhost = false;
        using var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig);
        try
        {
            nancyHost.Start();
            Console.WriteLine($"Nancy now listening on {uri}...");
            Logger.LogInfo($"Nancy now listening on {uri}...");

            // spin thread here
            _semaphoreToRequestStop = new SemaphoreSlim(0);
            _thread = new Thread(DoWork);
            _thread.Start();

        }
        catch (Exception ex)
        {
            Logger.LogError(ex.Message);
            Console.WriteLine($"Error: {ex.Message}");
        }
    }

    private void DoWork(object obj)
    {
        while (true)
        {
            Console.WriteLine("doing work..");
            if (_semaphoreToRequestStop.Wait(500))
            {
                Console.WriteLine("Stopped");
                break;
            }
        }
    }

    public void Stop()
    {
        Logger.LogInfo("NancyDataService stopping...");
        _semaphoreToRequestStop.Release();
        _thread.Join();
        //return true;
    }

}

So now when I run the project in design mode (which Topshelf says you should be able to do), it seems to start fine and Nancy seems to be listening on the right port. However, when I go to the browser and type in HTTP//localhost:8080/, I get "This site can't be reached. localhost refused to connect"

I have the latest version of Topshelf (4.2.1) and Topshelf.Log4Net packages.

Can anyone shed any light on this? Thanks...

1

There are 1 best solutions below

0
RMittelman On

Solved this issue. Turned out to be incorrect scoping of my NancyHost object. Works fine now.