如何编写Web API,自托管,Windows服务

时间:2015-11-05 04:13:26

标签: c# windows-services asp.net-web-api

我无法理解这一点。我一直有异常

抛出异常:' System.AggregateException'在mscorlib.dll中,带有消息:"表达式计算器中的内部错误。"并没有内在的例外!

除了启动服务器之外,我无法找到错误的来源,此行:_server.OpenAsync()。Wait();

我认为使用DI和我是一个好主意,虽然我的问题来自Autofac,但正如你所看到的,我已经说了全部,我仍然得到这个例外。相关代码是最后一种方法。请看一下代码:

这是我的控制器代码:

using System;
using System.ServiceProcess;
using System.Threading;
using System.Reflection;
using ServicesUtilities;
using System.Web.Http;
using System.Web.Http.SelfHost;
using Autofac;
using Autofac.Integration.WebApi;

namespace SeviceMerge
{

    partial class MergeService : ServiceBase, IQuasiServiceBase
    {
        private HttpSelfHostServer _server;
        private bool _runOnStart;
        public InjectionService()
        {
            InitializeComponent();
            _runOnStart = Config.Run;
        }

        protected override void OnStart(string[] args)
        {
            WebApiListener();
        }

        protected override void OnStop()
        {
            _runOnStart = false;

            _server.CloseAsync().Wait();
            _server.Dispose();
        }
        void IQuasiServiceBase.OnStart(string[] args, bool isBatchMode)
        {
            OnStart(args);
        }

        void IQuasiServiceBase.OnStop()
        {
            OnStop();
        }

        bool IQuasiServiceBase.PauseCheck()
        {
            return false;
        }

        bool IQuasiServiceBase.StopCheck()
        {
            return false;
        }

        private void WebApiListener()
        {
            var config = new HttpSelfHostConfiguration("http://localhost:26675");

            config.Routes.MapHttpRoute(
                "Presents",
                "api/{controler}/{id}",
                new { id = RouteParameter.Optional }
            );

            _server = new HttpSelfHostServer(config);
            _server.OpenAsync().Wait();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

.net core 中的一切都从一个简单的控制台应用程序开始,这里我给您 5 个简单的步骤,您可以使用这些步骤在工作服务中自托管 Web API/Web 应用程序并在您的应用程序中托管最终的 .exe windows 服务,甚至你可以在 Linux Systemd 中托管,只需稍加改动。

我创建了一个非常简单的 Worker-Service Web-API 模板,该模板存在于我的 GitHub 个人资料中。以下步骤 100% 有效,但如果您遇到任何问题,您可以在这里提问,或者您可以从我的 GitHub 中克隆模板并使用它并阅读那里的文档。

执行以下步骤:

  1. 创建一个 .net 核心控制台应用程序。
  2. 使用 NuGet 安装包“Microsoft.AspNetCore.App”和“Microsoft.Extensions.Hosting.WindowsServices”。
  3. 创建一个 Worker.cs 文件来处理您的工作器服务。将以下代码放入:
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace WorkerServiceWebAppTemplate
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}
  1. 创建一个 Startup.cs 文件,该文件将处理您的 Web 主机并在根地址中创建一个简单的 GET API,并负责显示一条简单的消息。你可以扩展它。将以下代码行放入您的 Startup.cs 文件中:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;

namespace WorkerServiceWebAppTemplate
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();
            else
                app.UseHsts();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
}
  1. 最后要启动工作服务并在工作服务中托管您的 Web API,并且为了让您发布的 .exe 文件能够在 Windows 服务中托管,请在您的 Program.cs 中使用以下代码:< /li>
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WorkerServiceWebAppTemplate
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        private static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                .UseWindowsService()
                .ConfigureServices((hostBuilderContext, services) =>
                {
                    services.AddHostedService<Worker>();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }
    }
}