ASP.NET Core — знакомство

В очередной статье про .NET Core хочу начать знакомство со структурой проекта ASP.NET Core. Рассмотрим Kestrel и как он взаимодействует с приложением. Разберемся с содержимым файлов Program.cs и класса Startup.

Знакомство с проектом следует начать с файла Program.cs. Да, это именно тот файл, который мы привыкли видеть в консольных приложениях, ведь веб-приложения .NET Core представляют собой обычные исполняемые файлы. В дальнейшем, я буду рассматривать версию с ASP.NET Core 2.0 и выше, но для начала будет очень полезно посмотреть на содержимое файла для версии 1.0

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();
 
    host.Run();
}

Здесь строится экземпляр WebHost, он конфигурируется, а затем запускается.

.UseKestrel() — задаёт настройки для работы Kestrel веб-сервера. Данный метод может принимать KestrelServerOptions класс, который позволяет задать различные параметры настройки.

.UseContentRoot(Directory.GetCurrentDirectory()) — указываем текущий каталог в качестве корневого.

.UseIISIntegration() — добавляем интеграцию с IIS. IIS используется как обратный прокси сервер для Kestrel, именно так IIS взаимодействует с приложением, а выполняет код ASP.NET Core уже Kestrel сервер.

.UseStartup<Startup>() — задаёт файл запуска, в котором определяются настройки сайта.

Здесь я немного отвлекусь с расскажу про Kestrel.

Схема взаимодействия с Kestrel

Изображение взято из статьи: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel

Раньше, при разработке ASP.NET приложений IIS сервер был основным (можно считать единственным) вариантом запуска веб-приложений. Сам по себе IIS отличный сервер, но он ориентирован на Windows окружение. С приходом .NET Core и Kestrel ситуация поменялась, так как этот сервер является кроссплатформенным, отлично работает на Windows, Linux и macOS машинах. Использование таких серверов как IIS, Apache, Nginx для проксирования Kestrel позволяет работать с ASP.NET Core приложениями на этих серверах. Использование именно этих серверов предпочтительно, так как они обладают куда большими возможностями чем сам Kestrel, как например, управление нагрузкой, но вы можете использовать Kestrel напрямую, например, при разработке в VS это можно сделать, выбрав требуемый профиль в конфигурации, он будет совпадать с названием проекта:

Запуск Kestrel сервера в Visual Studio

Приложение будет запущено в консоли. Здесь же будет отображаться информация о состоянии запросов на сервере.

Запущенное .NET Core приложение в консоле, через Kestrel сервер

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

ASP.NET Core приложение открытое в браузере

Откуда здесь "Hello World!" разберёмся немного позже.

Теперь давайте посмотрим содержимое файла Program.cs в ASP.NET Core 2.0

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

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .Build();

Как можно заметить, он стал меньше, но параметров настройки не стало меньше, напротив. Мы можем посмотреть реализацию метода CreateDefaultBuilder здесь https://github.com/aspnet/MetaPackages/blob/dev/src/Microsoft.AspNetCore/WebHost.cs

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder()
        .UseKestrel((builderContext, options) =>
        {
            options.Configure(builderContext.Configuration.GetSection("Kestrel"));
        })
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            var env = hostingContext.HostingEnvironment;

            config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                  .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

            if (env.IsDevelopment())
            {
                var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                if (appAssembly != null)
                {
                    config.AddUserSecrets(appAssembly, optional: true);
                }
            }

            config.AddEnvironmentVariables();

            if (args != null)
            {
                config.AddCommandLine(args);
            }
        })
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
            logging.AddDebug();
        })
        .UseIISIntegration()
        .UseDefaultServiceProvider((context, options) =>
        {
            options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        });

    if (args != null)
    {
        builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
    }
    return builder;
}

Использование задания конфигурации аналогичной первой версии также остаётся допустимой.

Теперь рассмотрим файл Startup.cs.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

Класс Startup является точкой входа для приложения. Сейчас он содержит 2 метода

ConfigureServices — определяет сервисы, которые используются в вашем приложение, например ASP.NET Core MVC, Entity Framework Core, Identity.

Пример:

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

services.AddMvc();

services.AddTransient<IEmailSender, AuthMessageSender>();

С Dependency injection в ASP.NET Core будем разбираться позднее.

Configure — данный метод настраивает то, как ваше приложение будет отвечать на HTTP-запросы. Делается это путём добавления компонентов к экземпляру IApplicationBuilder Именно здесь нужно настраивать маршруты для MVC, страницы ошибок и прочее:

if (env.IsDevelopment())
{
    app.UseBrowserLink();
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

Для ранее созданного пустого приложения данный метод содержит вывод "Hello World!". Именно отсюда передаются эти данные.

app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });

На этом первый этап знакомства с ASP.NET Core можно завершить. Не забывайте попробовать всё на практике. О новых возможностях ASP.NET Core поговорим в следующих статьях.

Приятного программирования.

Добавить комментарий