Closed aL3891 closed 5 years ago
You're right on all counts.
Don't worry about using UseServer, it takes an instance. Directly registering with DI will make it easier for you to resolve services.
Great :) Is there anything else to think about with the move to generic host in .net core 3? Following some prs and digging though the code I've gathered that a web app is just a HostedService in the new model(?), is it still the case that IServer is a Singleton or is it scoped?
(Or actually, maybe you can already register IServer as scoped today and just create a scope for each server? I don't remember if you can override registrations in a child scope)
No, IServer is still a singleton in the new generic host scenario.
Cool np, thanks for the info! I ended up with this as a poc, perhaps it will be of use to someone :)
public class Program
{
public static Task Main(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseMultiServer<KestrelServer, TestServer>()
.UseStartup<Startup>()
.Build()
.RunAsync();
}
public class MultiServer<TServer1, TServer2> : MultiServer, IServer where TServer1 : IServer where TServer2 : IServer
{
public MultiServer(TServer1 server1, TServer2 server2) : base(new IServer[] { server1, server2 }) { }
}
public class MultiServer : IServer
{
public IServer[] Servers { get; }
public IFeatureCollection Features { get; set; } = new FeatureCollection();
public MultiServer(IServer[] servers)
{
Servers = servers;
foreach (var f in servers.SelectMany(s => s.Features))
Features[f.Key] = f.Value;
}
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) =>
Task.WhenAll(Servers.Select(s => s.StartAsync(application, cancellationToken)));
public Task StopAsync(CancellationToken cancellationToken) =>
Task.WhenAll(Servers.Select(s => s.StopAsync(cancellationToken)));
public void Dispose()
{
foreach (var s in Servers)
s.Dispose();
}
}
public static class ServerExtensions
{
public static IWebHostBuilder UseMultiServer<TServer1, TServer2>(this IWebHostBuilder hostBuilder) where TServer1 : class, IServer where TServer2 : class, IServer =>
hostBuilder.ConfigureServices(services =>
{
services.AddSingleton<TServer1, TServer1>();
services.AddSingleton<TServer2, TServer2>();
services.AddSingleton<IServer, MultiServer<TServer1, TServer2>>();
});
}
public class TestServer : IServer
{
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public IFeatureCollection Features { get; } = new FeatureCollection();
public void Dispose() { }
}
Hello folks, I'm sorry if this is a noob question, but i'm looking at ways to make an asp.net core application available both over regular http as well as via a custom server. i'd like both servers to pipe into the "same" application so that they share di and any other state that comes with the host if possible.
Basically I want to be able to process requests coming in both over http and from somewhere else, (in my case in memory but could be from anywhere)
As far as I understand, the best way to do this is to implement IServer on my own custom server and do a
UseServer()
with that, but since I also want to have kestrel listen to requests, I've been thinking I should make a wrapperIServer
implementation that starts both my server and kestrel.Is this line of thinking correct or is there a better/ built in way to do this? as far as I understand there can only be one IServer implementation registered