我创建了一个自托管的web api应用程序,作为Windows服务运行,使用TopShelf和Autofac进行依赖注入。
这是我的StartUp逻辑:
public class ApiShell : IApiShell
{
public void Start()
{
using (WebApp.Start<Startup>("http://localhost:9090"))
{
Console.WriteLine($"Web server running at 'http://localhost:9090'");
}
}
internal class Startup
{
//Configure Web API for Self-Host
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
GlobalConfiguration.Configuration
.EnableSwagger(c => c.SingleApiVersion("v1", "Swagger UI"))
.EnableSwaggerUi();
//default route
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
app.UseWebApi(config);
}
}
}
我按照以下方式启动WebApp:
public class HostService
{
//when windows service statrts
public void Start()
{
IoC.Container.Resolve<IApiShell>().Start(); //start web app
IoC.Container.Resolve<IActorSystemShell>().Start();
}
//when windows service stops
public void Stop()
{
IoC.Container.Resolve<IActorSystemShell>().Stop();
}
}
TopShelf配置:
HostFactory.Run(x =>
{
x.Service<HostService>(s =>
{
s.ConstructUsing(name => new HostService());
s.WhenStarted(sn => sn.Start());
s.WhenStopped(sn => sn.Stop());
});
x.RunAsLocalSystem();
x.SetDescription("Sample Service");
x.SetDisplayName("Sample Service");
x.SetServiceName("Sample Service");
});
我的控制器:
public class PingController : ApiController
{
private IActorSystemShell _actorSystem;
public PingController(IActorSystemShell actorSystem)
{
_actorSystem = actorSystem;
}
[HttpGet]
public async Task<string> Ping()
{
var response = await _actorSystem.PingActor.Ask<PingMessages.Pong>(PingMessages.Ping.Instance(),
TimeSpan.FromSeconds(10));
return response.PongMessage;
}
}
我也安装了Swagger,但是无法使用以下任一尝试访问我的控制器:
我错过了什么?
你不能这样做:
using (WebApp.Start<Startup>("http://localhost:9090"))
{
Console.WriteLine($"Web server running at 'http://localhost:9090'");
}
在写入行之后,在使用中不再有语句,因此使用将关闭,从而停止Web应用程序。这是其中一种情况,即使WebApp.Start
的结果是IDisposable,你也不应该使用using语句。相反,这样做:
public class ApiShell : IApiShell
{
_IDisposable _webApp;
public void Start()
{
_webApp = WebApp.Start<Startup>("http://localhost:9090");
Console.WriteLine($"Web server running at 'http://localhost:9090'");
}
public void Stop()
{
_webApp.Dispose();
}
}
public class HostService
{
public void Start()
{
IoC.Container.Resolve<IApiShell>().Start(); //start web app
}
public void Stop()
{
IoC.Container.Resolve<IApiShell>().Stop(); //stop web app
}
}
您尚未显示您的依赖项注册,但请确保将IApiShell
注册为单例,以便您启动/停止相同的实例。
请注意,如果这是传统的控制台应用程序而不是Windows服务,您可以这样做:
using (WebApp.Start<Startup>("http://localhost:9090"))
{
Console.WriteLine($"Web server running at 'http://localhost:9090'");
Console.WriteLine("Press any key to exit.");
Console.ReadKey(true);
}
ReadKey方法将使using语句保持活动状态,从而防止Web应用程序被处置。