How to start a AspNetCore App from an existing windows service

1

I have an existing windows service. The goal is to have a REST interface to communicate with this service. I thought it might be a good idea to just make a ASP.NET Core Web Application (see screenshot) and simply start the whole thing inside my existing service. Then they could share the same IOC container and so on.

enter image description here

Then I registered the service with sc create s1 binPath = "pathgoeshere"

When I start the service (attach to process for debugging) I get an error in the output window:

Exception thrown: 'System.DllNotFoundException' in Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll
The thread 0x5250 has exited with code 0 (0x0).
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
'WindowsService1.exe' (CLR v4.0.30319: WindowsService1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceProcess.resources\v4.0_4.0.0.0_de_b03f5f7f11d50a3a\System.ServiceProcess.resources.dll'. Module was built without symbols.
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
The thread 0x4fa0 has exited with code 0 (0x0).
Microsoft.AspNetCore.Server.Kestrel: Warning: Unable to bind to http://localhost:5000 on the IPv4 loopback interface: 'Die DLL "libuv": Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden.'.
Exception thrown: 'System.DllNotFoundException' in Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll
The thread 0x58c4 has exited with code 0 (0x0).
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Microsoft.AspNetCore.Server.Kestrel: Warning: Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Die DLL "libuv": Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden.'.
Exception thrown: 'System.IO.IOException' in Microsoft.AspNetCore.Server.Kestrel.Core.dll
Exception thrown: 'System.IO.IOException' in mscorlib.dll
Exception thrown: 'System.IO.IOException' in mscorlib.dll
Exception thrown: 'System.IO.IOException' in mscorlib.dll
Microsoft.AspNetCore.Server.Kestrel: Critical: Unable to start Kestrel.

I put the whole example on GitHub:

https://github.com/SuperSludge/aspnetcoreService

Has someone ever done something like this? Am I completely on the wrong path? Is it easier to rewrite the whole windows service as a ASP.NET Core App?

c#
asp.net-core
windows-services
asked on Stack Overflow Aug 23, 2018 by Mat • edited Aug 23, 2018 by Shaun Luttin

2 Answers

2
Do you need ASP.NET core application or just expose REST endpoints ? I am thinking you are trying to use it for the benefits of the library. If latter is true,   
 I have done a similar thing where we have exposed some REST endpoints hosted in our legacy Windows service through "Microsoft.Owin.Hosting". This looks exactly like the ASP.NET WEPAPI

    1) In your windows service, you can start the WebApp like

           //WEBAPI URL
           private const string WEBAPI_BASEADDRESS = "https://+:{port number}/";
           // declare a Idisposable variable
           private IDisposable webAPI;
           //Use Microsoft Owin's library to start it up
           webAPI = WebApp.Start<Startup>(url: WEBAPI_BASEADDRESS);

    //above "Startup" is a class you would declare in your other class library (see below number 2)


    2) You can create a new C# class library with a class named "Startup"  and use the system.Web.Http "Httpconfiguration" class as below

    /// <summary>
    /// Web API startup method
    /// </summary>
    public class Startup
    {
        private const string TOKEN_URL = "/api/token";
        private const string BASE_URL = "/api/{controller}/{id}";
        // This code configures Web API. The Startup class is specified as a type
        // parameter in the WebApp.Start method.
        public void Configuration(IAppBuilder appBuilder)
        {

            // Configure Web API for self-host. 
            HttpConfiguration config = new HttpConfiguration();
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: BASE_URL,
                defaults: new { id = RouteParameter.Optional }
            );

            appBuilder.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString(TOKEN_URL),
                Provider = new CustomAuthorizationServerProvider()
            });
            appBuilder.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

            //Swagger support
            SwaggerConfig.Register(config);
            //appBuilder.UseCors(CorsOptions.AllowAll);
            appBuilder.UseWebApi(config);
        }
    }

    3) Above code has a CustomAuthorizationProvider where you can declare your own Custom OAuth Authorization and do any kind of authentication you want as below

        public class CustomAuthorizationServerProvider : OAuthAuthorizationServerProvider

    and override the "`public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)`"

4) Then you can just spin up WebAPI controllers
    [Authorize]
    public class XXXController : ApiController
    {
}

Hope this helps . Let me know if something is not clear.
answered on Stack Overflow Aug 23, 2018 by Kaushik Srinath
1

If you want to have a REST Api in your service, you should add the WebApi in the service project not in a different project. So, in this case, I don't think you can use Asp.Net Core.

Use Owin to launch the Rest Api inside the service and run the service in another thread.

// declare baseUrl in confing file by ex
// Startup is your Startup class
using (WebApp.Start<Startup>(baseUrl))
{
     System.Console.WriteLine($"Listening on {baseUrl}");
     Thread.Sleep(Timeout.Infinite);
}

Imo, you should have another service to run this API, so in that way, you can use Asp.Net.Core.

The Windows Service do some logic and the WebApi use the same Business Api to interfere with the same Db.

answered on Stack Overflow Aug 23, 2018 by Zysce • edited Aug 23, 2018 by Zysce

User contributions licensed under CC BY-SA 3.0