Первый проект в ASP.NET 5

Давеча я покопался в новом ASP.NET и решил накидать инструкцию, как настроить проект, стартуя с темплейта Empty. Нам понадобятся: Visual Studio 2015 RC, MSSQL Server Express. В общем-то и все.

Сразу предупрежу, что использовать все это пока в каких-то реальных проектах невозможно, потому что ломается то тут, то там, да и разработчики так и пишут – мол, глубокая бета, только на свой страх и риск.

Часть 0. Подготовка.

Если это еще не сделано, сначала необходимо установить DNVM (.NET Version Manager), для чего запустите PowerShell от имени администратора и выполните команду @powershell -NoProfile -ExecutionPolicy unrestricted -Command "&{$Branch='dev';iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}".

Если же DMVM уже установлен, обязательно его обновите. Опять же, для этого нужно запустить PowerShell с правами администратора и выполнить команду  Set-ExecutionPolicy Unrestricted -Scope Process -Force, а затем dnvm upgrade.

Почти все ниже описанное относится к версии beta5.

Часть 1. Настройка MVC.

Итак, первым делом создаем новый проект ASP.NET Web Application, не забыв указать, что используем фреймворк версии 4.6.

ASP.NET Web Application

Далее выбираем Пустой шаблон в ASP.NET 5 Preview Templates.

ASP.NET 5 Preview Empty Template

В класс Startup (про него можно почитать тут) добавляем поле Configuration:

public IConfiguration Configuration { get; set; }

А также конструктор:

public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
    var configurationBuilder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
        .AddJsonFile("config.json")
        .AddEnvironmentVariables();

    Configuration = configurationBuilder.Build();
}

Идем в project.json и добавляем в dependencies следующие строки:

 "Microsoft.Framework.Runtime.Abstractions": "1.0.0-beta5",
 "Microsoft.Framework.Configuration": "1.0.0-beta5",
 "Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta5",
 "Microsoft.Framework.Configuration.Json": "1.0.0-beta5"

После добавления строк и сохранения файла Visual Studio сама подгрузит нужные пакеты. Не забываем добавить сам конфигурационный файл (ASP.NET Configuration File).

Идем дальше, добавляем поддержку Mvc в проект. Не закрывая файл project.json, дописываем:

"Microsoft.AspNet.Mvc": "6.0.0-beta5"

В метод ConfigureServices вставляем следующий код:

services.AddMvc();

А в метод Configure, заменяя уже существующий там, такой:

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

Пришло время сравнить. Сейчас файл Startup.cs должен выглядеть у вас так:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.AspNet.Hosting;

namespace MySite.Web
{
    public class Startup
    {
        public IConfiguration Configuration { get; set; }

        public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
        {
            Configuration = new ConfigurationBuilder(appEnv.ApplicationBasePath)
                .AddJsonFile("config.json")
                .AddEnvironmentVariables();
        }
        
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

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

Теперь можно добавить первый контроллер. Создаем папку Controllers и в ней MVC Controller Class с названием HomeController. Далее добавляем папку Views, а в ней папку Home, и создаем там MVC View Page с именем Index. Можно написать что-нибудь и запустить проект, текст должен отобразиться.

Home page

Часть 2. Настройка Entity Framework

Что ж, пора подключаться к базе данных. Добавим новый проект в наше решение, на этот раз Class Library.

Class Library Project

Открываем project.json, в dependencies прописываем:

"EntityFramework.SqlServer": "7.0.0-beta5",
"EntityFramework.Commands": "7.0.0-beta5"

Также на одном уровне с dependencies добавляем раздел commands, это необходимо для запуска миграций:

"commands": {
  "ef": "EntityFramework.Commands"
},

Создадим папку Tables, и добавим в нее классы Country и City:

public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }

    public ICollection<City> Cities { get; set; }

    public Country()
    {
        Cities = new List<City>();
    }
}

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int CountryId { get; set; }
    public Country Country { get; set; }
}

Теперь можно создать контекст. Добавляем класс SiteContext:

public class SiteContext : DbContext
{
    public DbSet<Country> Countries { get; set; }
    public DbSet<City> Cities { get; set; }
}

В качестве временного хака (потом можно вынести конфигурации в общую папку, либо настроить копирование) будем считывать конфигурацию из нашего проекта MySite.Web. в SiteContext добавим метод:

protected override void OnConfiguring(EntityOptionsBuilder optionsBuilder)
{
    var configuration = new Configuration().AddJsonFile("../MySite.Web/config.json");
    optionsBuilder.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"]);
}

Создадим в локальном MSSQL сервере базу данных MySite (либо в другом месте, но ConnectionString соответственно будет другим, см. connectionstrings.com) и обновляем наш файл конфига config.json в проекте MySite.Web:

{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(local);Database=MySite;Trusted_Connection=True;"
    }
  }
}

Наконец можно создать начальную миграцию. Практически везде написано использовать k, однако в последний момент все изменилось, и теперь нужная нам утилита называется dnx.

Открываем директорию с нашей библиотекой.

Open Folder in File Explorer

И запускаем PowerShell.

Run PowerShell

Вводим dnx . ef migration add initial для генерации, затем dnx . ef migration apply для применения к базе данных.

Вот собственно и все. Добавим через интерфейс SSMS Россию и пару городов.

SSMS

Добавим в метод ConfigureServices класса Startup конфигурацию Entity Framework’а:

services.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<SiteContext>();

И обновим HomeController:

public class HomeController : Controller
{
    protected readonly SiteContext Db;

    public HomeController(SiteContext context)
    {
        Db = context;
    }

    public IActionResult Index()
    {
        var country = Db.Countries.FirstOrDefault();
        var city = Db.Cities.Where(x => x.CountryId == country.Id).ToList();
        var result = String.Format("{0}: {1}", country.Name, String.Join(", ", country.Cities.Select(x => x.Name)));
        ViewBag.Result = result;

        return View();
    }
}

Конечно же вы удивитесь – что за странный код: почему не используется Using и зачем выбираются отдельно города. Странное дело, в beta5 Entity Framework’а пропали Using, все асинхронные методы (хотя вот в beta4 все было), и если не выбрать города, то в country поле City будет пустым…

На этом пока завершу. Ежели сил хватит, и лень меня не переборет, в следующей заметке расскажу про настройку NPM, Grunt и Bower.

P.S. Про EF в будущем можно будет почитать здесь.