在 ASP.NET Core 程序启动前运行你的代码

原文:在 ASP.NET Core 程序启动前运行你的代码

一、前言#

在进行 Web 项目开发的过程中,可能会存在一些需要经常访问的静态数据,针对这种在程序运行过程中可能几乎不会发生变化的数据,我们可以尝试在程序运行前写入到缓存中,这样在系统后续使用时就可以直接从缓存中进行获取,从而减缓因为频繁读取这些静态数据造成的应用数据库服务器的巨大承载压力。

既然需要在程序运行前将静态数据写入到缓存中,毫无疑问我们需要在程序运行前执行一些自定义功能的代码,那么在本章中,我将会介绍如何在 ASP.NET Core 项目中,实现在程序启动前执行某些特定功能的代码。

二、Step by Step#

1、先说结论#

因为这一篇文章更多的是在说明我在解决这个问题时的一步步思考,并没有涉及到代码的编写,所以下面的内容可能对你的帮助并不是很大,所以这里提前将实现的方式告诉大家。对于这个问题来说,只需要将我们想要执行的代码放到下面代码中注释所在的位置,即可实现我们的需求。

public class Program
{
  public static void Main(string[] args)
  {
    var host = CreateHostBuilder(args).Build();

    // do what you want

    host.Run();
  }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

2、前车之鉴#

在尝试如何在 ASP.NET Core 中实现这一功能需求前,我们可以看看在 .NET Framework 中如何实现这一功能,是不是可以对我们在后续的功能实现中提供某些借鉴。

对于采用 .NET Framework 的应用程序来说,项目创建后会生成一个 Global.asax 文件,在这个类文件中存在着 Application_Start 这样的一个方法,而 Application_Start 这个方法实际上是在当应用程序接收到第一个 HTTP 请求时触发,也就是说,当系统运行后第一次接收到用户的请求,就会触发 Application_Start 中的代码逻辑,后续不管再接收到多少的请求,都不会再触发该方法。

例如在这个基于 .NET Framework 构建的 MVC 项目模板中,在程序运行前需要执行注册路由信息、注册过滤器、注册使用 bundle 压缩后的 js、css 文件等等。

但是在 ASP.NET Core 项目中,并没有原生存在这样的方法,那么我们如何在 ASP.NET Core 应用中自己动手实现类似的功能呢?

3、后事之师#

了解了在之前版本中的实现方式,现在我们仔细看看 Application_Start 这个方法中执行的每行代码的功能,是不是特别像我们在 ASP.NET Core 项目中使用的各种中间件?

然而,如果你有使用过 ASP.NET Core 后就会知道,ASP.NET Core 中的中间件是会在每次请求时都会触发的,虽然我们可以在我们自定义的中间件中设置缓存中不存在数据就写入,存在就直接跳过的代码逻辑,但是既然除了第一次访问时才会真正执行该中间件的功能,后面完全用不到,因此,对于我这种略微强迫症的童鞋来说,这个真的不能忍。。。

既然中间件不可以,而我们需要的仅仅是只运行一次,提到 .NET Core,不知道你的第一印象是什么,对于我个人来说,无处不在的依赖注入,可能是我在 18 年开始学习 .NET Core 时的第一印象。我们知道,对于 .NET Core 中原生的依赖注入组件,存在着三种生命周期:Singleton、Scoped 以及 Transient,对于这三种生命周期的具体解释,还是推荐博客园里蒋金楠老师的一篇文章(电梯直达)。

对于采用 Singleton 方式注入的服务来说,因为是一种类似于全局单例的形式,不管后续从何处进行访问,都会访问的是同一个实例,那么,这里是不是就可以在此基础上实现我们的需求了呢?

很不幸,这里其实是有个很严重的逻辑上的问题的,依赖注入最终的目的是为了实现将我们定义的服务契约与实现进行解耦,实现服务的消费者只需要告诉依赖注入容器自己所需要服务的类型(服务接口 or 抽象服务类),就能自动得到与之匹配的服务实例。

简单点说就是,消费方要告诉服务提供方你要开始使用某个服务了,我才能给你提供对应的服务,就像我们去饭店吃饭,在点了菜后,没有必要关心厨师是用天然气 or 煤气给你烧的菜,但是能不能上菜的关键在于我们有没有点菜。因此,这个问题最终还是落在了我们应该在程序中的什么地方去调用我们设定好的方法。

绕了一圈,似乎我们的想法越来越偏,离我们想要实现的越来越远,既然路偏了,那就直接回到起点吧,抛弃我们在 .NET Framework 项目中的经验,重新从 ASP.NET Core 项目的启动流程开始看起。

在 ASP.NET Core 应用的启动过程中存在着两个非常重要的对象,对应到我们采用的 ASP.NET Core 3.X 的项目中则是 Host 以及 HostBuilder。这里的 Host 就是承载我们 Web 应用运行的载体,而 HostBuilder 则是用来构建 Host 对象的。

PS:因为 ASP.NET Core 3.0 开始加入了 对于 gRPC 框架和 Windows Service 的支持,同时为了与其它非 Web 服务器方案进行集成,因此将原来的 WebHost 和 WebHostBuilder 替换成了新的通用主机(generic-host)配置的模式 。当然,在 3.X 版本你还是可以使用 WebHost 和 WebHostBuilder 的,不过当然是不推荐的。

因为对于 ASP.NET Core 应用程序来说,本质上其实只是一个控制台应用,所以现在我们来看看对于一个控制台应用中最重要的文件:Program.cs, Program 类中的代码如下所示。

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

代码很少,功能也很简单,简单来说,在 Main 方法中构建 HostBuilder 对象,然后去运行它,达到启动我们 Web 应用宿主的目的。

当然,在构建 HostBuilder 对象的过程中,会配置 Kestrel 服务器,会设置 ContentRoot,会加载配置文件等等一系列的动作,因为自己水平太次,尝试了一下,还是解释不好,如果你想要深入了解的话,建议配合博客园里面的这两篇文章一起食用(200行代码,7个对象——让你了解 ASP.NET Core 框架的本质ASP.NET Core 2.0 : 七.一张图看透启动背后的秘密)。虽然参考文章中都是基于 ASP.NET Core 2.X 版本进行解释说明的,但其实最终的差异不是很大。

不知你是否找到了这个类中对于我们最重要的一点,在 Main 方法中,我们是先构建、再去运行,因此,我们是不是可以在构建完成后,先等一等,把我们想要实现的功能先调用了,再去运行我们的程序。嗯,让我们改造下 Main 方法中的代码。

public class Program
{
    public static void Main(string[] args)
    {
    var host = CreateHostBuilder(args).Build();

    // Get logger
    //
    var logger = host.Services.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("haha, I ran before web host starting");

    host.Run();
  }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

从上面的图中可以看到,在我们的 Web 应用的宿主程序还未启动之前,控制台就已经打印出了我们自己设定的信息,之后,才是启动我们的 Web 应用,这里是请求我们的 API 接口。同时可以发现,在模拟多次请求时,并不会再次触发我们预设的事件。

三、总结#

这一篇文章中并没有包含代码,更多的是针对我之前在开发中遇到的一个问题,自己在解决过程中的一个案例说明,希望可以在你以后遇到这类问题时可以提供一些帮助。离 2020 年的农历新年也没有几天了,按目前的进度,估计就是年前的最后一篇博客了,我也要收拾收拾心情,准备过年了。最后,送大家一张表情包,献给得知你是最后一个放假的童鞋,哈哈哈,提前祝大家新年快乐丫。

四、参考#

  1. [ASP.NET Core 3框架揭秘] 依赖注入[8]:服务实例的生命周期
  2. 200行代码,7个对象——让你了解 ASP.NET Core 框架的本质
  3. ASP.NET Core 2.0 : 七.一张图看透启动背后的秘密
  4. ASP.NET Core 3.0 的新增功能

原文地址:https://www.cnblogs.com/lonelyxmas/p/12239106.html

时间: 2024-10-08 10:48:35

在 ASP.NET Core 程序启动前运行你的代码的相关文章

如何在ASP.NET Core程序启动时运行异步任务(2)

原文:Running async tasks on app startup in ASP.NET Core (Part 2) 作者:Andrew Lock 译者:Lamond Lu 在我的上一篇博客中,我介绍了如何在ASP.NET Core应用程序启动时运行一些一次性异步任务.本篇博客将继续讨论上一篇的内容,如果你还没有读过,我建议你先读一下前一篇. 在本篇博客中,我将展示上一篇博文中提出的"在Program.cs中手动运行异步任务"的实现方法.该实现会使用一些简单的接口和类来封装应用

如何优雅的利用Windows服务来部署ASP.NET Core程序

上一篇文章中我给大家讲述了五种部署ASP.NET Core网站的方法,其中有一种方式是通过Windows服务来进行部署,这样既可以做到开启自启动,又不会因为iis的反向代理而损失部分性能.但是美中不足的是需要借助第三方软件nssm来进行,那么有没有更好并且优雅的方式来进行ASP.NET Core网站的Windows服务方式部署呢?答案是肯定的! 作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/10380887.html 今天这篇文章我会利用番茄工作法来

ASP.NET Core教程:ASP.NET Core 程序部署到Windows系统

一.创建项目 本篇文章介绍如何将一个ASP.NET Core Web程序部署到Windows系统上.这里以ASP.NET Core WebApi为例进行讲解.首先创建一个ASP.NET Core WebApi项目,使用默认的Values控制器,这里使用Visual Studio 2019创建一个ASP.NET Core 3.1d的WebApi项目. 创建新项目的时候选项ASP.NET Core Web应用程序,如下图所示: 配置新项目界面界面设置项目名称和位置,如下图所示: 选择.Net Cor

ASP.NET Core教程:ASP.NET Core程序部署到Linux

一.前言 这篇文章我们将讲解如何将ASP.NET Core 程序部署到Linux.这里我们使用的是虚拟机里面安装的Centos7.这里的ASP.NET Core程序,以上篇文章中发布的框架依赖文件为例进行讲解. 二.安装运行时环境 1.在线安装 我们只是在Linux系统上面部署应用程序,所以只需要安装ASP.NET Core Runtime即可.在安装.NET之前,我们需要先注册Microsoft密钥和源,在终端里面执行下面的命令: sudo rpm -Uvh https://packages.

重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性

[源码下载] 作者:webabcd 介绍重新想象 Windows 8.1 Store Apps 之后台任务的新特性 下载和上传的新特性 程序启动前预下载网络资源 后台任务的其它新特性 示例1.本例用于说明 win8.1 中后台下载和上传的新特性(本例用后台下载说明,后台上传与此类似)TransferNew.xaml <Page x:Class="Windows81.BackgroundTask.TransferNew" xmlns="http://schemas.mic

ASP.NET CORE做的网站运行在docker上(不用dockerfile文件部署)

原文:ASP.NET CORE做的网站运行在docker上(不用dockerfile文件部署) 按网上的做法用dockerfile文件是可以弄得出来的,http://www.docker.org.cn/article/119.html, 不过我想把网站文件放在外面硬盘目录,再映射进去,这样只要在硬盘目录中修改CSHTML文件后重启一下容器就行了 步骤如下: 1. vs中建立ASP.NET CORE网站,类名为coreweb1 2. 发布到c:\temp\coreweb1目录 3. 先在本地CMD

ASP.NET应用程序自己重启的方法的代码

把开发过程比较常用的一些代码做个备份,如下代码段是关于ASP.NET应用程序自己重启的方法的代码. private static void RestartMe() { Application.ExitThread(); Application.Exit(); Application.Restart(); Process.GetCurrentProcess().Kill(); } 原文地址:http://blog.51cto.com/14149868/2342430

asp.net core在Centos7环境运行配置

环境说明: 服务器系统:CentOS 7.2.1511 相关工具:Xshel.Xftp 服务器软件软件:.netcore.nginx.supervisor 准备好发布的程序 安装.NET Core SDK for CentOS7   打开网址:https://www.microsoft.com/net/core#linuxcentos 复制如下命令,单步执行: sudo yum install libunwind libicu   curl -sSL -o dotnet.tar.gz https

《ASP.NET Core 高性能系列》ASP.NET Core的启动过程(1)

一.一切从头开始 简述:知道事情的真相就应该从头 开始,下面我们代码先行 public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWeb