Где разместить логику запуска приложений в ASP.NET Core - PullRequest
0 голосов
/ 12 октября 2018

Я хочу создать веб-сервис с ASP.NET Core 2.1, который проверяет при запуске приложения, работает ли соединение с базой данных, а затем подготавливает некоторые данные в базе данных.

Проверка выполняется в цикле, пока соединение не будет успешным или пользователи не нажмут Ctrl + C (IApplicationLifetime).Важно, чтобы HTTP-вызов не обрабатывался до инициализации базы данных.Мой вопрос: где поставить этот код?

Мне нужно, чтобы система внедрения зависимостей была полностью инициализирована, поэтому самое раннее, о чем я мог подумать, было бы в конце моего Startup.Configure метода, но токены отмены на IApplicationLifetime, похоже, не работаюттам (правильно, потому что asp не полностью запущен)

Есть ли официальное место, где можно поместить эту логику запуска?

Ответы [ 3 ]

0 голосов
/ 13 октября 2018

где поставить этот код?

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 */
0 голосов
/ 07 августа 2019

Я хочу создать веб-службу с ASP.NET Core 2.1, которая проверяет запуск приложения

Так, например, у меня был сценарий, чтобы проверить структуру папок, если не создать еекак только приложение запускается.

Метод создания структуры папок находится в FileService.cs , который должен быть инициирован через DI, как только приложение запускается перед любым запросом http. 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();
    }
0 голосов
/ 13 октября 2018

Вы можете создать метод расширения из 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();
}
...