Создание контроллера и инициализатора базы данных

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 16.11.2019

Чтобы у нас в базе данных уже были начальные данные при запуске приложения, нам нужен некий класс. который бы выполнял роль инициализатора базы данных. Для этого добавим в проект новый класс, который назовем SampleData и который будет иметь следующий код:

using System.Linq;
using MobileStore.Models;

namespace MobileStore
{
    public static class SampleData
    {
        public static void Initialize(MobileContext context)
        {
            if (!context.Phones.Any())
            {
                context.Phones.AddRange(
                    new Phone
                    {
                        Name = "iPhone X",
                        Company = "Apple",
                        Price = 600
                    },
                    new Phone
                    {
                        Name = "Samsung Galaxy Edge",
                        Company = "Samsung",
                        Price = 550
                    },
                    new Phone
                    {
                        Name = "Pixel 3",
                        Company = "Google",
                        Price = 500
                    }
                );
                context.SaveChanges();
            }
        }
    }
}

Данный класс определяет один статический метод Initialize(), в котором происходит добавление трех начальных элементов - объектов Phone. Для добавления объектов в бд в метод Initialize передается контекст данных. И если данные в таблице Phones в бд отсутствуют (if (!context.Phones.Any())), то добавляются три объекта.

Чтобы инициализатор базы данных вызывался при старте приложения, изменим класс Program следующим образом:

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MobileStore.Models;

namespace MobileStore
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;

                try
                {
                    var context = services.GetRequiredService<MobileContext>();
                    SampleData.Initialize(context);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred seeding the DB.");
                }
            }
            host.Run();
        }

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

В данном случае получаем контекст из сервисов и вызываем инициализатор. В случае ошибки осуществляем логгирования через соответствующий сервис.

Итак, начальные данные определены, и теперь мы хотим их выводить на веб-страницу, чтобы пользователи видели набор товаров и смогли бы один из них выбрать.

Для этого перейдем к папке Controllers, где находится единственный контроллер HomeController. Изменим его содержимое следующим образом:

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using MobileStore.Models;

namespace MobileStore.Controllers
{
    public class HomeController : Controller
    {
        MobileContext db;
        public HomeController(MobileContext context)
        {
            db = context;
        }
        public IActionResult Index()
        {
            return View(db.Phones.ToList());
        }
    }
}

Во-первых, здесь удалены все ненужные нам методы - все кроме метода Index, который будет использоваться для передачи пользователю данных о товарах.

Во-вторых, добавлен конструктор, в котором получаем контекст данных. Здесь применяется встроенный механизм внедрения зависимостей. Так как, в методе ConfigureServices() контекст данных был добавлен в качестве сервиса:

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

То через конструктор мы можем получить эту зависимость и использовать ее.

Затем вызывается метод View(), который генерирует представление. И в этот метод передаются все объекты из таблицы Phones в базе данных. Для передачи данных нам достаточно использовать такую конструкцию: db.Phones.ToList().

За построение визуального интерфейса в MVC отвечают представления. И теперь создадим само представление для вывода списка смартфонов. Для представлений в проекте предназначена папка Views. По умолчанию в этой папке уже есть подкаталог для представлений контроллера Home, в котором три представления: About.cshtml, Contact.cshtml и Index.chtml.

Каждый метод контроллера по умоланию использует одноименное представление. То есть метод Index будет использовать представление Index.cshtml. Откроем это представление и изменим его код следующим образом:

@model IEnumerable<MobileStore.Models.Phone>
@{
    //ViewData["Title"] = "Список смартфонов";
    Layout = null;
}
<!DOCTYPE html>

<html>
<head>
    <title>Магазин смартфонов</title>
</head>
<body>
    <h3>Смартфоны</h3>
    <table>
        <tr>
            <td>Модель</td>
            <td>Производитель</td>
            <td>Цена</td>
            <td></td>
        </tr>
        @foreach (var phone in Model)
            {
            <tr>
                <td>@phone.Name</td>
                <td>@phone.Company</td>
                <td>@phone.Price</td>
                <td><a href="~/Home/Buy/@phone.Id">Купить</a></td>
            </tr>
        }
    </table>
</body>
</html>

Представления напоминают html-страницы, так как могут содержать и часто содержат очень много кода html. Но кроме собственно html они также содержат специальные инструкции, которые предваряются символом @. Это инструкции синтаксиса Razor - специального движка представлений, который позволяет использовать вместе с html и код на языке c#. Далее мы подробнее разберем синтаксис движка Razor, а пока достаточно знать, что после символа @ идут выражения на языке C#.

Первая строка устанавливает модель представления - та сущность, которая будет доступна в представлении через объект Model. В данном случае это объект IEnumerable<MobileStore.Models.Phone>, так как в контроллере в методе Index мы передаем список смартфонов, а список - объект List представляет интерфейс IEnumerable.

Далее идет блок кода, в котором выражение Layout = null указывает, что мастер-страница не будет применяться к этому представлению. Далее мы добавим к нему мастер-страницу и узнаем, зачем она нужна, а пока обойдемся без нее.

Практически весь остальной код представляет собой стандартный код веб-страницы на языке html: создание обычной таблицы, которая выводит информацию о продаваемых смартфонах. Здесь также используется конструкция @foreach (var phone in Model). То есть тут мы создаем цикл. В нем мы пробегаемся по всем элементам в объекте Model, который представляет переданный в методе Index список смартфонов. И затем получаем значение свойства каждого элемента с помощью синтаксиса Razor: @phone.Name и помещаем его в ячейку таблицы.

В последнюю колонку таблицы для каждого элемента добавляется ссылка <a href="~/Home/Buy/@phone.Id">Купить</a>. При нажатии на эту ссылку методу Buy контроллера HomeController будет отправляться запрос, в котором вместо @phone.Id будет указан id смартфона. Пока у нас, правда, отсутствует метод Buy, но скоро мы его создадим.

Основы маршрутизации

В методе Configure() класса Startup устанавливаются настройки маршрутизации приложения:

app.UseEndpoints(endpoints =>
{
	endpoints.MapControllerRoute(
		name: "default",
		pattern: "{controller=Home}/{action=Index}/{id?}");
});

Здесь добавляется маршрут с именем default. Поле pattern указывает, что запрос к приложению должен иметь двух-трехсегментную структуру. Вначале идет имя контроллера, потом имя метода и потом может идти необязательный параметр id.

То есть чтобы обратиться к контроллеру HomeController или отправить ему запрос, нам надо указать в строке запроса его имя - Home и далее через слеш указать метод контроллера, к которому отправляется запрос, например, Home/Index. По умолчанию при запуске проекта или при обращении к сайту система mvc будет вызывать действие Index контроллера HomeController.

Теперь запустим приложение на выполнение. По умолчанию, как и определено выше маршрутом default, сработает обращение к методу Index контроллера Home, который возвратит пользователю страницу с данными:

Первое приложение на ASP.NET MVC Core

А через интерфейс Visual Studio в окне SQL Server Object Explorer мы можем увидеть созданную базу данных:

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850