簡體   English   中英

將應用程序啟動邏輯放在ASP.NET Core中的位置

[英]Where to put application startup logic in ASP.NET Core

我想用ASP.NET Core 2.1創建一個Web服務,如果與數據庫的連接工作,則檢查應用程序啟動,然后在數據庫中准備一些數據。

檢查以循環方式運行,直到連接成功或用戶按下Ctrl + C( IApplicationLifetime )。 在初始化數據庫之前,沒有處理HTTP調用很重要。 我的問題是:在哪里放這個代碼?

我需要一個完全初始化的依賴注入系統,所以我能想到的最早就是我的Startup.Configure方法的結尾,但IApplicationLifetime上的取消令牌似乎不適用於那里(因為asp不是完全開始)

有一個官方的地方可以把這個啟動邏輯?

您可以從IWebHost構建一個擴展方法,它允許您在Startup.cs之前運行代碼。 此外,您可以使用ServiceScopeFactory初始化您擁有的任何服務(例如DbContext )。

public static IWebHost CheckDatabase(this IWebHost webHost)
{
    var serviceScopeFactory = (IServiceScopeFactory)webHost.Services.GetService(typeof(IServiceScopeFactory));

    using (var scope = serviceScopeFactory.CreateScope())
    {
        var services = scope.ServiceProvider;
        var dbContext = services.GetRequiredService<YourDbContext>();

        while(true)
        {
            if(dbContext.Database.Exists())
            {
                break;
            }
        }
    }

    return webHost;
}

然后你可以使用該方法。

public static void Main(string[] args)
{
    BuildWebHost(args)
        .CheckDatabase()
        .Run();
}

在哪里放這個代碼?

class Initializer
{
    internal static SemaphoreSlim _semaphoreSlim;
    static SemaphoreSlim Slim
    {
        get
        {
            return LazyInitializer.EnsureInitialized(ref _semaphoreSlim, () => new SemaphoreSlim(1, 1));
        }
    }

    public static void WaitOnAction(Action initializer)
    {
        Initializer.Slim.Wait();
        initializer();
        Initializer.Slim.Release();
    }
}

有一個官方的地方可以把這個啟動邏輯?

Startup.cs是開始的好地方......

Initializer.WaitOnAction(()=> /* ensure db is initialized here */); 
/* check https://dotnetfiddle.net/gfTyTL */

我想用ASP.NET Core 2.1創建一個Web服務,它檢查應用程序啟動

因此,例如,我有一個場景來檢查文件夾結構,如果不是在應用程序啟動后立即創建文件夾結構。

創建文件夾結構的方法是在FileService.cs中 ,只要應用程序在任何http請求之前啟動,就必須通過DI啟動它。 appsettings.json包含鍵和值,其中包含用於創建文件夾結構的結構。

"FolderStructure": {
    "Download": {
      "English": {
        "*": "*"
      },
      "Hindi": {
        "*": "*"
      }
    },
    "Upload": {
      "*": "*"
    }
  }

並在接口和服務下面使用

接口

namespace MyApp.Services
{
    public interface IFileService
    {
        void CreateDirectoryStructure(string path = "");
        void CreateFolder(string name, string path = "");
        void CreateFile(string name, string path = "");
        bool CheckFileExists(string path);
        bool CheckFolderExists(string path); 
    }
}

服務

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Configuration.Binder;
using System.IO;
using Microsoft.Extensions.Logging;

namespace MyApp.Services
{
    public class FileService : IFileService
    {
        private readonly IFileProvider _fileProvider;
        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly IConfiguration _config;
        private readonly ILogger<FileService> _logger;
        string defaultfolderPath = ConfigurationManager.AppSetting["DefaultDrivePath"];
        public FileService(IFileProvider fileProvider, IHostingEnvironment hostingEnvironment, IConfiguration config, ILogger<FileService> logger)
        {
            _fileProvider = fileProvider;
            _hostingEnvironment = hostingEnvironment;
            _config = config;
            _logger = logger;
        }
        public void CreateDirectoryStructure(string drivePath = "")
        {     
            if (drivePath.Equals(""))
            {
                drivePath = ConfigurationManager.AppSetting["DefaultDrivePath"];
                _logger.LogInformation($"Default folder path will be picked {drivePath}");
            }
            foreach (var item in _config.GetSection("FolderStructure").GetChildren())
            {
                CreateFolder(item.Key, drivePath);
                foreach (var i in _config.GetSection(item.Path).GetChildren())
                {
                    if (i.Key != "*")
                        CreateFolder(i.Key, $"{drivePath}/{item.Key}");
                }
            }
        }
        public void CreateFolder(string name, string path = "")
        {
            string fullPath = string.IsNullOrEmpty(path) ? $"{defaultfolderPath}/{name}" : $"{path}/{name}";
            if (!Directory.Exists(fullPath))
            {
                Directory.CreateDirectory(fullPath);
                _logger.LogInformation($"Directory created at {fullPath} on {DateTime.Now}");
            }
        }
        public void CreateFile(string name, string path = "")
        {
            string fullPath = string.IsNullOrEmpty(path) ? $"{defaultfolderPath}/{name}" : $"{path}/{name}";
            if (!File.Exists(fullPath))
            {
                File.Create(fullPath);
                _logger.LogInformation($"File created at {fullPath} on {DateTime.Now}");
            }
        }
        public bool CheckFolderExists(string path)
        {
            string fullPath = string.IsNullOrEmpty(path) ? defaultfolderPath : path;
            return Directory.Exists(fullPath);
        }

        public bool CheckFileExists(string path)
        {
            string fullPath = string.IsNullOrEmpty(path) ? defaultfolderPath : path;
            return File.Exists(fullPath);
        }

    }
}

現在的挑戰是在應用程序啟動后立即調用文件夾服務方法,但我們需要通過DI初始化文件服務

  services.AddSingleton<IFileService, FileService>();

在Configure方法中,您可以調用所需的服務。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IFileService FileService)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
        //dont change the below order as middleware exception need to be registered before UseMvc method register
        app.ConfigureCustomMiddleware();
        // app.UseHttpsRedirection();
        app.UseMvc();
        FileService.CreateDirectoryStructure();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM