【问题标题】:Application startup code in ASP.NET CoreASP.NET Core 中的应用程序启动代码
【发布时间】:2016-12-27 02:21:16
【问题描述】:

阅读documentation for ASP.NET Core,为启动选择了两种方法:Configure 和 ConfigureServices。

这些似乎都不是放置我想在启动时运行的自定义代码的好地方。也许我想在我的数据库中添加一个自定义字段(如果它不存在)、检查特定文件、将一些数据植入我的数据库等。我想在应用程序启动时运行一次的代码。

是否有首选/推荐的方法来执行此操作?

【问题讨论】:

  • 添加此评论,因为我觉得它有助于保持 Startup.cs 文件干净,以获得已接受的解决方案:odetocode.com/blogs/scott/archive/2016/08/30/…
  • 我知道这是在 2016 年提出的,但同样的问题在 2018 年仍然存在,您应该考虑我提出的观点并重新考虑接受的答案。

标签: c# asp.net-core startup


【解决方案1】:

此类自定义代码在启动时基本上有两个入口点。

1.) Main 方法

作为一个 ASP.NET Core 应用程序有很好的旧 Main 方法作为入口点,您可以在 ASP.NET Core 启动内容之前放置代码,例如

public class Program
{
    public static void Main(string[] args)
    {
        // call custom startup logic here
        AppInitializer.Startup();

        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

2.) 使用您的 Startup

正如您在问题中所述,ConfigureConfigureServices 是您自定义代码的好地方。

我更喜欢Startup 类。从运行时的角度来看,调用是在启动时调用还是在 host.Run() 调用之前的其他地方调用都没有关系。但从习惯于 ASP.NET 框架的程序员的角度来看,他首先寻找这种逻辑将是Startup.cs 文件。所有示例和模板都将身份、实体框架初始化等逻辑放在那里。因此,作为惯例,我建议将初始化的东西放在那里。

【讨论】:

  • Startup 类还提供了内置依赖注入容器IServiceProvider 通过IApplicationBuilder.ApplicationServices 属性在ConfigureServices 中可用的好处。
  • OP 说“这些似乎都不是放置自定义代码的好地方”,并不是说它们是一个好地方。
【解决方案2】:

我同意 OP。

我的场景是我想向服务注册表注册一个微服务,但在微服务运行之前无法知道端点是什么。

我觉得 Configure 和 ConfigureServices 方法都不理想,因为它们都不是为了执行这种处理而设计的。

另一种情况是想要预热缓存,这也是我们可能想要做的事情。

接受的答案有几种选择:

  • 创建另一个在您的网站之外执行更新的应用程序,例如部署工具,它在启动网站之前以编程方式应用数据库更新

  • 在您的 Startup 类中,使用静态构造函数确保网站已准备好启动

更新

在我看来,最好的做法是像这样使用 IApplicationLifetime 接口:

public class Startup
{
    public void Configure(IApplicationLifetime lifetime)
    {
        lifetime.ApplicationStarted.Register(OnApplicationStarted);
    }

    public void OnApplicationStarted()
    {
        // Carry out your initialisation.
    }
}

【讨论】:

  • 我发现一个请求处理已经开始了(它已经开始执行一个中间件),而 OnApplicationStarted 方法还没有完成。就我而言,它正在启动事务,而数据库尚未更新。 ApplicationStarted 文档还说:“在应用程序主机完全启动并即将等待正常关闭时触发。”这并不意味着在请求处理开始之前它不是一些初始化东西的地方。
  • 请注意,IApplicationLifetime 在 .NET 3.x 中已弃用,新接口现在称为:IHostApplicationLifetime
【解决方案3】:

这可以通过创建一个IHostedService 实现并在您的启动类中使用IServiceCollection.AddHostedService&lt;&gt;() in ConfigureServices() 注册它来完成。

示例

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;

public class MyInitializer : IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        // Do your startup work here

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        // We have to implement this method too, because it is in the interface

        return Task.CompletedTask;
    }
}
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHostedService<MyInitializer>();
    }
}

注意事项

【讨论】:

    猜你喜欢
    • 2020-11-29
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 2018-06-02
    • 2017-09-03
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    相关资源
    最近更新 更多