在不使用 asp.net 的情况下在 .net 核心应用程序中自托管 HTTP(s) 端点?

Self hosting HTTP(s) endpoints in .net core app without using asp.net?

我在 Windows 和 Linux 中也有一个 .net 核心应用程序 运行(我使用 .net 核心运行时 >= 2.1)。为了获得更好的见解,我想公开一个指标端点(简单的 HTTP GET 端点),以便 Prometheus 发布我的应用程序的一些内部统计信息。

通过 WWW 搜索,所以我总是最终使用 asp.net 核心。由于我只想向现有的 .net 核心应用程序添加一个非常简单的 HTTP GET 端点,因此将整个应用程序移植到 asp.net.

似乎有点矫枉过正。

我已经考虑过的备选方案是编写我自己的基于 HttpListener 的处理程序。当涉及到一个简单的 HTTP 端点时,这是非常简单的,但是由于我找到的所有关于 SSL 和 Linux 的信息都是,目前不支持,我应该使用 asp.net。 (https://github.com/dotnet/runtime/issues/33288#issuecomment-595812935)

所以我想知道我误解了什么!我是唯一一个? 是否已经有一个很好的库为 .net 核心提供简单的 http(s) 服务器?

编辑:[已解决] 正如@ADyson 在下面的评论中提到的,现有应用程序不需要移植到 asp.net 核心!

自动添加2.1版本dotnet new web生成的项目文件 引用 "Microsoft.AspNetCore.App""Microsoft.AspNetCore.Razor.Design"

当我从 .net 核心项目引用我的 asp.net 核心项目并执行托管 Web 服务的代码时,我最终得到一个 System.IO.FileNotFoundException 声明 "Could not load file or assembly 'Microsoft.AspNetCore.Mvc.Core'"

Microsoft.AspNetCore.App 是一个元包,也引用了 Microsoft.AspNetCore.MVC!因此,执行程序集也必须引用此元包。这个观察误导了我,使用 asp.net 核心渲染我的整个应用程序围绕 Microsoft.AspNetCore.App 构建。

删除这些引用并仅添加对 "Microsoft.AspNetCore" 的引用后,一切正常。

在检查了 3.1 版 dotnet new web 生成的项目文件后,这些引用没有被添加。对于使用较新版本的 dotnet 的人来说,这不是问题!

一种选择是使用 EmbeddIo

https://unosquare.github.io/embedio/

我发现文档并不总是最好的,尤其是当它们最近升级并且许多示例等无效时。但你可以到达那里!

您可以像这样自行托管 REST API:

 WebServer ws = new WebServer(o => o
        .WithUrlPrefix(url)
        .WithMode(HttpListenerMode.EmbedIO))
        .WithWebApi("/api", m => m
        .WithController<ApiController>());

this.Cts = new CancellationTokenSource();
var task = Webserver.RunAsync(Cts.Token);

然后像这样定义你的 API 控制器。

class ApiController : WebApiController
 {
        public ApiController() : base()
        {

        }

        [Route(HttpVerbs.Get, "/hello")]
        public async Task HelloWorld()
        {
            string ret;
            try
            {
                ret = "Hello from webserver @ " + DateTime.Now.ToLongTimeString();
            }
            catch (Exception ex)
            {
                //
            }
            await HttpContext.SendDataAsync(ret);

        }
}

@ADyson, OWIN is the way to go. You can easily self-host a HTTP endpoint in your existing application. Here is a sample to self-host it in a .Net Core 3.1 console application. It exposes a simple endpoint listening on port 5000 for GET requests using a controller. All you need is to install the Microsoft.AspNetCore.Owin Nuget 包所述。

代码文件结构如下:

.
├── Program.cs
├── Startup.cs
├── Controllers
    ├── SayHi.cs

Program.cs

using Microsoft.AspNetCore.Hosting;

namespace WebApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseUrls("http://*:5000")
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

Startup.cs

using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace WebApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

SayHi.cs

using Microsoft.AspNetCore.Mvc;

namespace WebApp.Controllers
{
    public class SayHi : ControllerBase
    {
        [Route("sayhi/{name}")]
        public IActionResult Get(string name)
        {
            return Ok($"Hello {name}");
        }
    }
}

然后一个简单的 dotnet WebApp.dll 将启动应用程序和网络服务器。 如您所见,示例使用了 Kestrel。默认网络服务器。您可以查看Microsoft的相关文档。

有关更多配置和路由选项,您可以查看 Microsoft 的文档。

在 2.1 版中使用 dotnet new web 生成的项目文件自动添加了对 "Microsoft.AspNetCore.App""Microsoft.AspNetCore.Razor.Design" 的引用,当被 .net 核心项目引用并执行时,它们以 System.IO.FileNotFoundException 说明 "Could not load file or assembly 'Microsoft.AspNetCore.Mvc.Core'".

在3.1版本中使用dotnet new web创建项目不引用这些,因此可以从.net core应用程序引用和执行该项目。

-> 使用 asp.net 核心对我来说是一个可行的解决方案(再次)!