self hosted ASP.NET Core Web Api capable of starting and stopping

304 views Asked by At

I'm attempting to convert an old WCF service to an ASP.NET Core Web API, making use of the CoreWCF package. A key feature of this existing service is that it's being self hosted by an other application and is able to gracefully start & stop, without creating memory leaks.

I have been able to figure out how to start and stop a prototype service. However, after performing some stress testing, it does seem like I've left a memory leak somewhere and I'm sadly out of ideas or available documentation at this point. I'm also considering that an ASP.NET Core Web API just isn't supposed to be used like this and I misunderstood this, if so, be sure to let me know. Also my apologies for the truckload of code, but I'm not sure what's relevant or not to the question.

The code for my prototype service looks like this:

Configuring the webhost:

private void CreateWebHostBuilder(){
    host = WebHost.CreateDefaultBuilder()
        .UseKestrel(options =>
        {
            options.AllowSynchronousIO = true;
            options.ListenLocalhost(Startup.PORT_NR);
            options.ConfigureHttpsDefaults(
             options => options.ClientCertificateMode = ClientCertificateMode.RequireCertificate
            );
        })
        .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); })
        .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
        .UseShutdownTimeout(TimeSpan.FromSeconds(1))
        .UseStartup<Startup>()
        .Build();
}

Inside the Startup class:

Configuring the IApplicationBuilder:

public void Configure(IApplicationBuilder app){
    app.UseServiceModel(builder =>
    {
        // Add the Echo Service
        builder.AddService<EchoService>()                
        // Add service web endpoint                
        .AddServiceWebEndpoint<EchoService, IEchoService>(
            WEB_API_PATH,behavior => { behavior.HelpEnabled = true;}
        );
     });            
     app.UseMiddleware<SwaggerMiddleware>();            
     app.UseSwaggerUI();
     app.UseAuthentication();
}

Configuring the services:

public void ConfigureServices(IServiceCollection services){
    services.AddServiceModelWebServices()                
            .AddHostedService<EchoService>()                       
            .AddSingleton(new SwaggerOptions())                  
            .AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
            .AddCertificate();            
}

The service interface:

[ServiceContract]
[OpenApiBasePath($"/{Startup.WEB_API_PATH}")]
public interface IEchoService : IHostedService {
    [OperationContract]
    [WebGet(UriTemplate = "/hello")]
    [OpenApiOperation(Description = "Method used to receive a friendly \"Hello world\"",
        Summary = "Hello world")]
    [OpenApiResponse(Description = "OK Response", StatusCode = HttpStatusCode.OK)]
    string HelloWorld();        
}

The implemented service:

public class EchoService : IEchoService {        
    public EchoService() { }

    public string HelloWorld() {
        return "Hello world!";
    }        
    public Task StartAsync(CancellationToken cancellationToken) {
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {            
        return Task.CompletedTask;
    }        
}

Creating and starting the host + services:

public void StartWebService(object obj){
    CreateWebHostBuilder();
    host.StartAsync();
}

Stopping and disposing the services and host:

public void StopWebService(object obj) {
    host.StopAsync().Wait();
    host.Dispose();                            
}

So if anyone has any suggestions or tutorial reference, be sure to let me know, any help is welcome.

0

There are 0 answers