Search code examples
owinnancytopshelf

Nancy.Owin vs Nancy.Hosting.Self with topshelf


1) What is the differences between setting up with the two different packages? Is one more supported than the other?

I had a project using Nancy.Hosting.Self and didn't find any article about how to setup windows authentication, while I did find it for Nancy.Owin as middleware. I have now switched to Nancy.owin.

Here are a few different questions.

2) The jsonformatter can be configured in both the nancy bootstrapper as in the owin endpoint topshelf. Where should I configure the formatter? If configured in the topshelf owin endpoint, will this be applied in the nancy bootstrapper as well?

3) With the nancy endpoint in topshelf there was an option to set firewall rules and url reservations. I can't find this in the owin endpoint.

private static void CreateHost(HostConfigurator host)
    {
        var logger = SetupLogging();
        host.UseSerilog(logger);
        host.UseLinuxIfAvailable();
        //sc => serviceconfigurator, ls => licenseService
        host.Service<WebService>(sc =>
        {
            sc.ConstructUsing(name => new WebService(_config));
            sc.WhenStarted(ls => ls.Start());
            sc.WhenStopped(ls => ls.Stop());
            sc.OwinEndpoint(app =>
            {
                app.ConfigureHttp(configuration =>
                {
                    //use json.net serializer
                    configuration.Formatters.Clear();
                    configuration.Formatters.Add(new JsonMediaTypeFormatter());

                    //configure json settings
                    var jsonSettings = configuration.Formatters.JsonFormatter.SerializerSettings;
                    jsonSettings.Formatting = Formatting.Indented;
                    jsonSettings.Converters.Add(new StringEnumConverter { CamelCaseText = false, AllowIntegerValues = true });
                    jsonSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                });
                app.ConfigureAppBuilder(builder =>
                {
                    builder.UseNancy(options =>
                    {
                        options.Bootstrapper = new Bootstrapper(_config);
                        //options.PerformPassThrough
                    });
                });
                app.ConfigureStartOptions(options =>
                {
                    options.Port = _config.LicenseServicePort;
                    //options.Urls = new List<string>(){};
                });
            });

            //add host reservation during service install, this is the only time, nancy will have admin rights, will be deleted when service is uninstalled as well.
            //nc => nancyConfig
            //sc.WithNancyEndpoint(host, nc =>
            //{
            //    nc.AddHost(port: _config.LicenseServicePort);
            //    nc.CreateUrlReservationsOnInstall();
            //    nc.DeleteReservationsOnUnInstall();
            //    nc.OpenFirewallPortsOnInstall(firewallRuleName: "mycustomservice");
            //    nc.Bootstrapper = new Bootstrapper(_config);
            //});
        });

        host.SetDescription("Licensing service for my api.");
        host.SetDisplayName("myservice");
        host.SetServiceName("myservice);
        host.RunAsNetworkService();
        host.StartAutomatically();
    }

Solution

  • Posted answer for codetoshare

    private static void CreateHost(HostConfigurator host)
        {
            Log.Logger = SetupLogging();
            host.SetStartTimeout(TimeSpan.FromSeconds(60));
            //Plug serilog into host: log startup urls and start / stop
            host.UseSerilog(Log.Logger);
    
            //Allow to be run on linux as well
            host.UseLinuxIfAvailable();
    
            //sc => serviceconfigurator, ls => licenseService
            host.Service<WebService>(sc =>
            {
                //basic topshelf configuration
                sc.ConstructUsing(name => new WebService());
                sc.WhenStarted(ls => ls.Start());
                sc.WhenStopped(ls =>
                {
                    ls.Stop();
                    DisposeLogging();
                });
                //I am using an extension here because I had converted the application from Nancy.Host.Self to Nancy.Owin
                //if the extension will not get updated and this breaks the application, convert it to a normal app: see nearly every topshelf + owin example
                //owin configuration
                sc.OwinEndpoint(app =>
                {
                    app.ConfigureHttp(configuration =>
                    {
                        //use json.net serializer
                        configuration.Formatters.Clear();
                        configuration.Formatters.Add(new JsonMediaTypeFormatter());
    
                        //configure json settings
                        var jsonSettings = configuration.Formatters.JsonFormatter.SerializerSettings;
                        jsonSettings.Formatting = Formatting.Indented;
                        jsonSettings.Converters.Add(new StringEnumConverter { CamelCaseText = false, AllowIntegerValues = true });
                        jsonSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                    });
    
                    app.ConfigureAppBuilder(builder =>
                    {
                        //setup windows authentication
                        HttpListener listener = (HttpListener)builder.Properties["System.Net.HttpListener"];
                        listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
    
                        //setup nancy
                        builder.UseNancy(options =>
                        {
                            options.Bootstrapper = new Bootstrapper(_config);
                        });
                    });
                    //setup urls: always add localhost and 127.0.0.1 together with the host specified in the config file
                    app.ConfigureStartOptions(options =>
                    {
                        options.Port = _config.LicenseServicePort;
                        var localhost = $"http://localhost:{_config.LicenseServicePort}";
                        var localhost2 = $"http://127.0.0.1:{_config.LicenseServicePort}";
                        //todo: this should support https as well
                        //todo: allow multiple hosts to be specified on config
                        options.Urls.Add(localhost);
                        options.Urls.Add(localhost2);
                        var configuredHost = $"{_config.LicenseServiceUrl}:{_config.LicenseServicePort}";
                        if (!configuredHost.Equals(localhost) && !configuredHost.Equals(localhost2))
                        {
                            options.Urls.Add(configuredHost);
                        }
                    });
                });
    
                //old nancyhost config, keep this untill documented on confluence
                //add host reservation during service install, this is the only time, nancy will have admin rights, will be deleted when service is uninstalled as well.
                //nc => nancyConfig
                //sc.WithNancyEndpoint(host, nc =>
                //{
                //    nc.AddHost(port: _config.LicenseServicePort);
                //    nc.CreateUrlReservationsOnInstall();
                //    nc.DeleteReservationsOnUnInstall();
                //    nc.OpenFirewallPortsOnInstall(firewallRuleName: "SegreyLicensingService");
                //    nc.Bootstrapper = new Bootstrapper(_config);
                //});
            });