ASP.NET Core i Visual Studio Code – pierwsze próby w Mac OS

ASP.NET Core to platforma do tworzenia aplikacji web od firmy Microsoft. Po co gigant wymyślił na nowo koło, gdy jest ASP.NET dla Windows? Opinie są różne – spotkałem się z głosami, że chodziło o zbyt niskie zainteresowanie ASP.NET MVC, ze względu na dostępność jedynie na jednej platformie. Opinie opierały się także o dużą popularność systemów Linux oraz MacOS wśród programistów, gdzie ASP.NET z Windows nie było dostępne. Jeszcze inni czuli po prostu niechęć do Microsoft lub obawiają się zmian w polityce licencyjnej producenta. Cóż, sam mam awersję do wszystkiego, co pochodzi od Microsoft. I nie jest to podyktowane jakąś chorą filozofią, ale wieloletnim doświadczeniem z niedopracowanymi produktami tej firmy. Poza tym – do czego programiście web .NET Core, skoro mamy tak wiele zupełnie darmowych, otwartych i stabilnych platform programistycznych? I chyba w końcu coś drgnęło, bowiem panowie z Microsoft postanowili podbić serca programistów do tej pory nieprzekonanych. Jednakże wiedzieli, że by do nich dotrzeć, należało stworzyć produkt międzyplatformowy i z naciskiem na narzędzie CLI (programiści pracujący na Linuksach czy Macach używają przede wszystkim terminala). Istotną kwestią była również licencja, bowiem programiści kochają wszystko, co jest oparte na otwartym kodzie. Microsoft zatem postanowił zdobyć zaufanie programistów i nieco złagodzić wizerunek złej korporacji poprzez hasła typu „Microsoft kocha open source”. Oczywiście to bzdura i bełkot marketingowy, zaś opracowanie Core było w interesie firmy. Ale tym razem przyznaję – starają się zrobić coś, co mnie bardzo zaciekawiło. Coś, co może wytrącić negatywne argumenty takim malkontentom, jak ja. Ale nie mogłem uwierzyć, dopóki osobiście nie przetestuję. Zatem postanowiłem poświęcić kilka dni i przetestować ASP.NET Core. Czy to faktycznie przełom? A może za wcześnie wciskają nam niedopracowany kit – podobnie jak wcisnęli Windows 10 będący w rzeczywistości w wersją beta? 

Przyjrzyjmy się zatem w kilku punktach cechom (pozytywnym) ASP.NET Core[1]:

  • jest to projekt open source – jest i pozostanie darmowe;
  • kompilowanie i uruchamianie aplikacji w systemach Windows, macOS i Linux.
  • przeznaczony do budowania aplikacji i usług internetowych, aplikacji IoT i zapleczy mobilnych;
  • można jej używać w w systemach Windows, macOS i Linux.;
  • aplikacje mogą być wdrażanie w chmurze lub lokalnie;
  • ujednolicono scenariusz na potrzeby tworzenia internetowego interfejsu użytkownika i internetowych interfejsów API;
  • wbudowane wstrzykiwanie zależności;
  • modułowy potok żądań HTTP zapewniający wysoką wydajność;
  • hostowanie w usługach IIS, Nginx, Apache, Docker lub samodzielnie we własnym procesie;
  • przechowywanie wersji aplikacji obok siebie, gdy platformą docelową jest .NET Core;
  • narzędzia Visual Studio (Windows/MacOS) oraz Visual Studio Code[1], które upraszczają tworzenie aplikacji;
  • konfiguracja za pomocą plików JSON a nie ciężkich do zrozumienia plików XMLowych;
  •  wzorzec MVC ułatwia możliwość testowania aplikacji internetowych i internetowych interfejsów API;
  • silnik Razor (w ASP.NET Core 2) to model programowania, umożliwiający tworzenie wydajnego interfejsu użytkownika;
  • helpery ułatwiają tworzenie i renderowanie elementów HTML w plikach Razor po stronie serwera;
  • obsługa wielu formatów danych oraz wielu przeglądarek i urządzeń przenośnych;
  • automatyczne mapowanie danych z żądań HTTP na parametry metod akcji;
  • możliwość przeprowadzania walidacji modelu po stronie klienta i serwera.

Jak zacząć pisać w ASP.NET Core

Przede wszystkim należy wyposażyć się w niezbędne narzędzia.

  1. W systemie Windows, należy zainstalować Visual Studio 2017 wraz z .NET Core

    źródło obrazka: Microsoft
  2. W Mac Os należy najpierw zainstalować Xcode, zaś później Visual Studio for Mac (lub pobrać wyłącznie SDK).
  3. W tym opisie będziemy korzystać z Visual Studio Code, zatem koniecznie należy zainstalować także Visual Studio Code. Jest to edytor programistyczny, który bardzo fajnie integruje się z .NET Core.

Tworzymy pierwszy projekt ASP.NET Core (Mac Os)

  1. Otwórz terminal i utwórz katalog dla nowego projektu poleceniem mkdir testowy <enter>
  2. Przejdź do nowo utworzonego katalogu poleceniem cd testowy <enter>
  3. Utwórz nowy projekt poleceniem dotnet new mvc <enter>

wynik polecenia:

iMac-Praca:testowy user$ dotnet new mvc
Pomyślnie utworzono szablon „ASP.NET Core Web App (Model-View-Controller)”.
Ten szablon zawiera technologie producentów innych niż firma Microsoft. Aby uzyskać szczegóły, zobacz https://aka.ms/template-3pn.

Trwa przetwarzanie akcji po utworzeniu…
Trwa uruchamianie polecenia „dotnet restore” dla /Users/user/Programowanie/testowy/testowy.csproj…
Restoring packages for /Users/user/Programowanie/testowy/testowy.csproj…
Restore completed in 92,81 ms for /Users/user/Programowanie/testowy/testowy.csproj.
Generating MSBuild file /Users/user/Programowanie/testowy/obj/testowy.csproj.nuget.g.props.
Generating MSBuild file /Users/user/Programowanie/testowy/obj/testowy.csproj.nuget.g.targets.
Restore completed in 1,82 sec for /Users/user/Programowanie/testowy/testowy.csproj.

Przywracanie powiodło się.

Oczywiście to samo można wykonać z poziomu Visual Studio, jednakże warto też pamiętać, że Visual Studio działa pod Windows oraz MacOS, zatem programiści Linuxa nie mogą skorzystać z dobrodziejstw pełnego IDE. Mimo wszystko skoro udostępnili CLI, to chciałem je przetestować. W końcu jestem przyzwyczajony do terminala. Microsoft w końcu stara się zrobić to, co we frameworkach php, rubym i pythonie było od zawsze i każdy o tym wie, jednak w przypadku ASP.NET Core propaganda w sieci aż huczy o przełomie i wyjątkowej efektywności CLI w Core.

Listę dostępnych opcji CLI można wyświetlić poprzez dotnet -h (my wybraliśmy opcję new, czyli inicjacja nowego projektu platformy .NET). Aby wyświetlić dostępne opcje dla new, należy wpisać: dotnet new <enter>. Wyświetli się lista dostępnych szablonów:

Szablony                           Krótka nazwa          Język                  Tagi
---------------------------------------------------------------------------------------------------
Console Application                  console            C#, F#, VB          Common/Console
Class library                        classlib           C#, F#, VB          Common/Library
Unit Test Project                    mstest             C#, F#, VB          Test/MSTest
xUnit Test Project                   xunit              C#, F#, VB          Test/xUnit
ASP.NET Core Empty                   web                C#, F#              Web/Empty
ASP.NET Core Web App (MVC)           mvc                C#, F#              Web/MVC
ASP.NET Core Web App                 razor              C#                  Web/MVC/Razor Pages
ASP.NET Core with Angular            angular            C#                  Web/MVC/SPA
ASP.NET Core with React.js           react              C#                  Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux         C#                  Web/MVC/SPA
ASP.NET Core Web API                 webapi             C#, F#              Web/WebAPI
global.json file                     globaljson                             Config
NuGet Config                         nugetconfig                            Config
Web Config                           webconfig                              Config
Solution File                        sln                                    Solution
Razor Page                           page                                   Web/ASP.NET
MVC ViewImports                      viewimports                            Web/ASP.NET
MVC ViewStart                        viewstart                              Web/ASP.NET

Teraz wystarczy uruchomić projekt poleceniem dotnet run <enter>

Hosting environment: Production
Content root path: /Users/user/Programowanie/testowy
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Jak widać powyżej, serwer pracuje w wersji produkcyjnej, na hoście lokalnym na porcie 5000. Wystarczy zatem otworzyć przeglądarkę i wpisać adres http://localhost:5000 aby zobaczyć szkielet aplikacji.

Aby zatrzymać serwer, wystarczy w terminalu wcisnąć Crl+C. Po tej operacji należy zamknąć WSC i zrestartować terminal. Jednakże uruchomione środowisko pracuje domyślnie w trybie produkcyjnym. Aby uruchomić je w trybie developerskim, należy ustawić zmienną i uruchomić serwer: ASPNETCORE_ENVIRONMENT=Development dotnet run. Można też ustawić na czas sesji zmienną poleceniem: export ASPNETCORE_ENVIRONMENT=Development. Od tej chwili, dopóki terminal będzie aktywny, polecenie dotnet run będzie uruchamiać środowisko w trybie developerskim.

Po zatrzymaniu, należy otworzyć projekt w edytorze Visual Studio Code. I tutaj niezbędna jest niewielka modyfikacja. Pracując w terminalu, dążymy do tego, by nie korzystać z Findera, lecz uruchamiać VSC z poziomu terminala komendą code <enter>. Jednakże prawdopodobnie nie uda się to bezpośrednio po zainstalowaniu VSC. Aby to poprawić, należy otworzyć z Findera VSC i w IDE wcisnąć kombinację klawiszy (⇧⌘P). Następnie wpisać w pole komendę Shell Command: Install ‚code’ command in PATH. Po tym należy ponownie uruchomić terminal aby uwzględnił nową zmienną.

źródło: Microsoft 

Teraz wystarczy wpisać polecenie: code . <enter>, aby otworzyć projekt. Tym razem otworzy się IDE – Visual Studio Code wraz nowo utworzonym projektem. Prześledźmy teraz strukturę katalogów utworzonego projektu. Będą nas interesować głównie katalogi: Controllers (kontrolery), Models (modele), Views (widoki) oraz wwwroot (zawiera pliki statyczne – css, obrazki, skrypty, lib – biblioteki, np. bootstap, jquery).

Dodawanie nowej strony (kontroler i widok)

I tutaj zaczyna się pierwszy problem programistów przesiadających się z PHP czy Rubiego – otóż w tych środowiskach można generować z CLI gotowe kontrolery i akcje. A w ASP.NET Core? W terminalu domyślnie nie ma – jakaś porażka. Można pobrać dodatkowe narzędzie, ale gdzie tu rewelacja?

Załóżmy, że chcemy utworzyć kontroler Books z akcją index oraz show. W tym celu w VSC kliknij prawym klawiszem myszy na pozycji Controllers i wybierz – New file. Nowy plik nazwij BooksController.cs i wpisz zawartość:

using Microsoft.AspNetCore.Mvc;
 
namespace testowy.Controllers
{
  public class BooksController : Controller
  {
      public string Index()
      {
          return "To jest wynik akcji Index kontrolera Books";
      }
 
      public string View()
      {
          return "To jest wynik akcji View kontrolera Books";
      }
  }
 
}

Następnie zapisz plik i uruchom środowisko testowe komendą: ASPNETCORE_ENVIRONMENT=Development dotnet run. Otwórz stronę w przeglądarce wpisując adres http://localhost:5000/Books a następnie http://localhost:5000/Books/View. Działa to podobnie jak w przypadku frameworków PHP. Jeśli zaś trzeba przekazać wyniki akcji do widoków, należy nieco zmodyfikować źródła.

Uwaga – VSC również potrafi debugować aplikację. W tym celu należy wcisnąć przycisk debugowania z lewego paska narzędzi. Środowisko zaproponuje pobranie pakietu debugowania, po czym za pomocą przycisku F5 będzie można uruchamiać aplikacje z poziomu SVC. Więcej o debugowaniu w VSC.

Najpierw należy dodać klasę Book.cs w katalogu Models:

public class Book
    {
        public long Id { get; set; }
        public string Title { get; set; }
        public string Author { get; set; }
    }

Następnie w pliku BooksConroller.cs:

public IActionResult Index()
      {
            Book myBook = new Book {
                Id = 1,
                Title = "Sztuka wojny",
                Author = "Sun Tzu"
            };
 
          ViewData["zmienna_do_widoku"] = myBook;
          return View();
      }

Oraz w pliku widoku Index.cshtml

@using testowy.Models
@{
    ViewBag.Title = "Index";
}
 
<h2>Witaj w akcji Index</h2>
 
<p>To jest templata kontrolera Books, akcja Index!</p>
 
 
@{
    //var zmienna = (Book)ViewData["zmienna_do_widoku"]; <- tak też można
    var zmienna = ViewBag.zmienna_do_widoku;
}
 
<h1>Książka</h1>
<h3>ID: @zmienna.Id</h3>
<h3>Tytuł: @zmienna.Title </h3>
<h3>Autor: @zmienna.Author</h3>

Jak widać w ASP.NET Core jest to dość proste i wydaje logiczne. Otwórz stronę Otwórz stronę w przeglądarce wpisując adres http://localhost:5000/Books i sprawdź, czy działa.

W ASP.NET Core CLI i VSC popełnianie niektórych błędów jest cięższe do wyśledzenia niż w przypadku pełnej wersji Visual Studio. Jak zadziała, to fajnie, jak nie, można ujrzeć np. taki oto komunikat i niewiele informacji o problemie.

Należy przyzwyczaić się do tego typu okienek – szczegółowe błędy wyświetlane są w terminalu – ale nie wszystkie.

Tymczasem próba uruchomienia błędnego kodu w Visual Studio Mac w prosty i czytelny sposób informuje o błędach.

Praca z bazą danych – migracje

Dotychczas skupiałem się wyłącznie nad pojęciem filozofii ASP.NET Core, lecz aplikacja web to przede wszystkim baza danych. Ale ASP.NET Core to nie Rails, Django czy Laravel. Tutaj najpierw należy się pomęczyć z instalacją bibliotek. Ale to nie wszystko, bowiem część rzeczy nie chce działać, wyrzucając błędy o konflikcie wersji. Trzeba umieć dobrze obsługiwać Google. Pierwszym etapem jest dodanie niezbędnych bibliotek, czyli w tym przypadku Entity Framework, aby w ogóle móc operować na bazach danych. W terminalu wywołaj polecenia:

  • dotnet add package Microsoft.EntityFrameworkCore <enter>,
  • dotnet add package Microsoft.EntityFrameworkCore.Design <enter>.
  • dotnet add package Microsoft.EntityFrameworkCore.SQLite <enter> (będziemy testować ASP.NEt Core na bazie SQLite).
  • Microsoft.EntityFrameworkCore.Tools.DotNet <enter>

Po każdym dodaniu odwołania, będą one widoczne w pliku testowy.csproj w sekcji lub wielu sekcjach ItemGroup. Teraz należy uruchomić polecenie dotnet restore <enter>. Uwaga – mogą dziać się rzeczy dziwne, albo prawidłowe – zależy od fazy księżyca. Przy próbach raz wszystko grało, innym razem występowały błędy. Aby sprawdzić, czy CLI dla Entity Framework działa, należy wpisać w terminalu polecenie dotnet ef <enter>. Jeśli wyświetlą się błędy, niestety nie wiem co zrobić. Metodą prób i błędów zaczęło działać. Oto mój plik testowy.csproj:

Project Sdk=”Microsoft.NET.Sdk.Web”>
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReferenceInclude=”Microsoft.AspNetCore.All”Version=”2.0.5″/>
<PackageReferenceInclude=”Microsoft.EntityFrameworkCore”Version=”2.1.1″/>
<PackageReferenceInclude=”Microsoft.EntityFrameworkCore.Design”Version=”2.1.1″/>
<PackageReferenceInclude=”Microsoft.EntityFrameworkCore.SQLite”Version=”2.1.1″/>
<PackageReferenceInclude=”Microsoft.EntityFrameworkCore.Tools.DotNet”Version=”2.0.0″/>
</ItemGroup>
<ItemGroup>
<DotNetCliToolReferenceInclude=”Microsoft.EntityFrameworkCore.Tools”Version=”2.0.0″/>
<DotNetCliToolReferenceInclude=”Microsoft.EntityFrameworkCore.Tools.DotNet”Version=”2.0.0″/>
</ItemGroup>
</Project>

Po tym należy ponownie wydać polecenie dotnet restore i jeśli nie wystąpią błędy zależności (pewnie jakieś ostrzeżenia będą, ale to nic), można wydać polecenie dotnet ef <enter>. Wynik powinien być następujący:

Mac-Praca:testowy user$ dotnet ef
 
                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\
 
Entity Framework Core .NET Command Line Tools 2.0.0-rtm-26452
 
Usage: dotnet ef [options] [command]
 
Options:
  --version        Show version information
  -h|--help        Show help information
  -v|--verbose     Show verbose output.
  --no-color       Don't colorize output.
  --prefix-output  Prefix output with level.
 
Commands:
  database    Commands to manage the database.
  dbcontext   Commands to manage DbContext types.
  migrations  Commands to manage migrations.
 
Use "dotnet ef [command] --help" for more information about a command.

Być może fani PHP już dali sobie spokój z ASP.NEt Core i przestali czytać niniejszy artykuł. Jeśli jednak ktoś dotrwał i dotychczasowe zabiegi działają, można przystąpić do modeli. W ASP.NET wiele rzeczy, niezależnie czy dotyczy bazy danych czy nie, odbywa się właśnie poprzez modele. I przyznam, że jest to bardzo logiczne i czytelne. Zatem teraz należy zmodyfikować nieco nasz model, aby przystosować go do bazy danych. Plik Book.cs należy zmienić , jak poniżej. Na razie baza będzie oparta na jednej tabeli.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
 
namespace testowy.Models
{
[Table("Books")]
public class Book
    {
        [Key]
        public long Id { get; set; }
 
        [Required(ErrorMessage = "Należy podać tytuł książki!")]
        [Display(Name = "Tytuł")]
        [MaxLength(200, ErrorMessage="Tytuł musi zawierać prznajmniej 5 znaków i nie więcej niż 200 znaków"),MinLength(5)]
        public string Title { get; set; }
 
        [MaxLength(200)]
        [Display(Name = "Autor książki")]
        public string Author { get; set; }
    }
}

Jak widać użyto adnotacji w celu walidacji danych. muszę przyznać, że jest to bardzo wygodne i proste z użyciu – no i przypomina mechanizmy walidacji modeli w PHP. Następnie należy utworzyć kontekst bazy danych. W tym celu trzeba utworzyć plik bazaDBContext.cs w folderze Models i wpisać nasępującą zawartość:

using Microsoft.EntityFrameworkCore;
using testy.Models;
 
namespace testowy
{
public class bazaDBContext : DbContext
{
    private static bool _created = false;
    public bazaDBContext()
    {
        if (!_created)
        {
            _created = true;
            Database.EnsureDeleted();
            Database.EnsureCreated();
        }
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
    {
        optionbuilder.UseSqlite("FileName=./BazaSQLite.db");
    }
 
    public DbSet<Book> Books { get; set; }
}
}

Po zapisaniu zmian, należy w terminalu ( w katalogu projektu) utworzyć pierwszą migrację poleceniem: dotnet ef migrations add InitialCreate <enter>. Polecenie sprawdzi, czy fizycznie istnieje baza danych i jeśli nie, zostanie ona utworzona. Dodatkowo zbuduje tabele w bazie danych zgodnie z modelami (w naszym przypadku tabelę Book). Warto także zauważyć, że w strukturze katalogu projektu pojawił się folder Migrations, w którym pojawiły się trzy pliki migracji:

  1. 00000000000000_InitialCreate.cs – główny plik migracji, który zawiera operacje konieczne do wywołania metod Up() – tworzenie oraz Down() – usuwanie.
  2. 00000000000000_InitialCreate.Designer.cs – plik migracji metadanych zawierający informacje używane przez Entity Framework.
  3. bazaContextModelSnapshot.cs – migawka bieżącego modelu, używana do określania, jakie będą zmiany podczas dodawania kolejnej migracji.

Pierwsze znaki w migracjach to sygnatury czasowe, które pomagają zachować porządek chronologiczny, związany z postępem zmian.

Migrację można cofnąć poleceniem ef migrations remove <enter>, co spowoduje usunięcie pliku bazy danych. Jeśli zajdzie potrzeba dołożenia nowego pola do tabeli Book (np. dodatkowe pole opis książki), wystarczy w klasie Book.cs je zdefiniować: public string Description { get; set; } i wywołać migrację poleceniem dotnet ef migrations add Book_AddFieldDescription<enter>, gdzie Book_AddFieldDescription to dowolna nazwa, która opisuje zmiany, jaką dokonaliśmy i aby łatwiej było odnaleźć informacje o zmianach.

CRUD dla modelu książek (Book)

W pliku Startup.cs należy zmodyfikować jedną linię, dodając kontekst bazy danych do serwisów:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<bazaDBContext>(options => options.UseSqlite("FileName=./BazaSQLite.db"));
}

Teraz całkowicie zmodyfikujemy BooksController.cs, aby wprowadzić do niego komplet operacji CRUD:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
using testowy.Models;
 
namespace testowy.Controllers
{
  public class BooksController : Controller
  {
      private readonly bazaDBContext _context;
 
    public BooksController(bazaDBContext context)
    {
      _context = context;
    }
 
 
        [HttpGet]
        public IActionResult Index()
        {
            var ksiazki = _context.Books.ToList();
            return View(ksiazki);
        }
 
        [HttpGet]
        public IActionResult Create() { 
            return View();
        }
 
        [HttpPost]
        public IActionResult Create(Book model) { 
            if (!ModelState.IsValid) return View(model);
            _context.Add(model);
            _context.SaveChanges();
            return RedirectToAction("index");
        }
 
        [HttpGet]
        public IActionResult Edit(long id) { 
            var ksiazki = _context.Books.Find(id);
            return View(ksiazki);
        }
 
        [HttpPost]
        public IActionResult Edit(Book model) { 
            if (!ModelState.IsValid) return View(model);
            _context.Books.Update(model);
            _context.SaveChanges();
            return RedirectToAction("index");
        }
 
        [HttpGet]
        public IActionResult Delete(long id){ 
           var ksiazki = _context.Books.Find(id);
           _context.Books.Remove(ksiazki);
           _context.SaveChanges();
           return RedirectToAction("index");
        }
  }
}

Pozostało jedynie dopisać odpowiednie widoki dla akcji Index, Create, Edit.

Katalog Views\Books, plik Index.cshtml

@model IEnumerable<testowy.Models.Book>
 
 <div class="panel-body">  
        <div class="btn-group">  
            <a asp-action="Create"  class="btn btn-primary">  
                <i class="glyphicon glyphicon-plus"></i>  Dodaj ksiązkę  
            </a>  
        </div>  
 
<br/> <br/>
 
 <table class="table table-bordered table-striped table-condensed">  
     <thead>  
       <tr>  
         <th>Tytuł</th>                      
         <th>Autor</th>
         <th>Operacje</th>  
        </tr>  
      </thead>  
         <tbody>  
           @foreach (var item in Model)  
             {  
              <tr>  
                <td>@Html.DisplayFor(modelItem => item.Title)</td>  
                <td>@Html.DisplayFor(modelItem => item.Author)</td>                       
               <td>  
          <a asp-action="Edit" asp-route-id="@item.Id" class="btn btn-info">  
          <i class="glyphicon glyphicon-pencil"></i>Edycja</a>  
          <a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-danger" onclick ="return confirm('Czy na pewno chcesz usunąć ?');">  
          <i class="glyphicon glyphicon-trash"></i> Usuń</a>  
                        </td>  
                    </tr>  
                }  
            </tbody>  
        </table>

Katalog Views\Books, plik Create.cshtml

@model testowy.Models.Book
 
<br/><br/>
<form asp-action="Create" method="Post">
     <div class="form-horizontal">
            <div class="row"> 
                <div class="form-group">  
                 <label asp-for="Title" class="col-lg-2 col-sm-3 control-label"></label>                           <div class="col-lg-3">  
                      <input asp-for="Title" class="form-control" />    
                      <span asp-validation-for="Title" class="text-danger"></span>                                  </div>  
                </div> 
 
    <div class="form-group">  
      <label asp-for="Author" class="col-lg-2 col-sm-3 control-label"></label>             
        <div class="col-lg-3">  
         <input asp-for="Author" class="form-control" />      
        </div>  
       </div>  
      </div>
   </div>
 
<input type="submit" value="Save" class="col-lg-2 col-md-offset-2 btn btn-success" /> <br/>
</form>

Katalog Views\Books, plik Edit.cshtml

@model testowy.Models.Book
 
<br/><br/>
<form asp-action="Edit" method="Post">
     <div class="form-horizontal">
       <div class="row"> 
         <div class="form-group">  
          <label asp-for="Title" class="col-lg-2 col-sm-3 control-label"></label>             
            <div class="col-lg-3">  
              <input asp-for="Title" class="form-control" />    
              <span asp-validation-for="Title" class="text-danger"></span>               
             </div>  
           </div> 
 
   <div class="form-group">  
      <label asp-for="Author" class="col-lg-2 col-sm-3 control-label"></label>             
         <div class="col-lg-3">  
            <input asp-for="Author" class="form-control" />      
         </div>  
        </div>  
     </div>
     </div>
<input type="submit" value="Update" class="col-lg-2 col-md-offset-2 btn btn-success" /> <br/>
</form>

Aplikacja działa. Ale ilość czasu, którą musiałem poświęcić jest przerażająca. Oczywiście wynika to z mojego niedoświadczenia w .NET, choć napisałem kilka prostych aplikacji w ASP.NET dla Windows. Tam jednak są dostępne kreatory i scaffolding. Być może w Core też są, ale nie korzystałem. A przecież aplikacja tu przedstawiona ma jedną tabelę – to tylko prymitywny przykład. W Railsach czy Django zrobiłbym to samo w kilka minut. Jednak w Core długo trwa konfiguracja projektu czy pobranie niezbędnych bibliotek. Czyli robota, której nie muszę wykonywać np. w CakePHP – wszystko jest out of the box[2]. Jednakże po testach odnoszę wrażenie, że logika pisania aplikacji w .NET charakteryzuje się pewną przewidywalnością, stąd rozbudowa aplikacji może być prosta, zaś w przypadku dużych systemów – czytelna dla programistów. Zaletą .NET Core jest też elastyczny sposób podejścia programisty w ekosystemie. Daną rzecz można wykonać na wiele sposobów – wszystko zależy od upodobań. Dodatkowo ASP.NET Core nie narzuca sztywnej struktury, a mimo to jest jednolite – nie mamy tutaj setek frameworków jak w przypadku PHP, lecz praktycznie jeden. Jak w Ruby i jego Railsach.

Chciałbym też przedstawić wnioski, które mi się nasunęły po kilku dniach w Visual Studio Code i ASP.NET Core w systemie Mac OS. Potraktujcie je jako wnioski programisty głównie PHP/JavaScript.

  • CLI nie działa jak trzeba, np. w Windows nie działa wcale – wyświetla błąd Failed to initialize CoreCLR, HRESULT: 0x80070057. Szczerze mówiąc nie chce mi się szukać rozwiązania, bo przecież powinno działać i już. Zresztą – po co komu Windows. Tylko sprawdzałem i nie działa.
  • Przenosząc pliki kompletnego projektu pomiędzy dwoma komputerami iMac, przy starcie VSC robi restore i uruchamia aplikację. Testowe przeniesienie z Maca na Windows, powoduje błędy zależności przy restore – nuget nie może czegoś odnaleźć. Pewnie da się to załatwić bowiem może chodzić o różne wersje zależności na Windows i MacOS, ale nie będę się tym zajmował.
  • Visual Studio 2017 dla Mac OS działa. Aktualizacje działają. Visual Studio 2017 Community dla Windows wyświetliło mi okno, w którym pisze, że nie mogę dłużej używać bieżącej wersji. Muszę zaktualizować i wtedy mogę. Po kliknięciu aktualizacji ściągnęło z 60MB, odpaliła się główna aktualizacja i wyświetliło się kolejne okno z napisem: „Nie mogliśmy zaktualizować, bo trwają inne aktualizacje”. Restart nie pomógł, Windows nie ma dostępnych aktualizacji. A może trwają aktualizacje aktualizacji? Porażka.
  • Im dłużej męczę ASP.NET Core, tym bardziej doceniam dopracowane, natychmiast działające i „wszystkotojużmające” frameworki PHP. No ale jest moda na ASP.NET Core – rzesze ewangelistów i słuchających ich studentów nie mogą się mylić. Zatem pewnie będę męczył się dalej. A w mojej opinii z tym .NET Core jest tak, że idea jest genialna, ale wykonanie słabe – zupełnie jak z Windows 10.
  • Na obecnym etapie rozwoju konsola CLI jest mocno niedopracowana – albo też wymaga sporych umiejętności pobrania dodatkowych narzędzi, konfigurowania, co zabiera czas. W Visual Studio programowanie jakoś idzie, ale w terminalu ciężko jest zacząć. Trzeba doinstalowywać jakieś dodatki, by w ogóle to funkcjonowało. Jeśli ktoś nigdy nie używał frameworków rails, django czy frameworków dostępnych dla PHP, nie zrozumie, że CLI w ASP.NET Core na chwilę obecną wypada marnie. Miejmy nadzieję, że to dopracują.
  • Język C#, jest czytelny, elastyczny i logiczny. To ogromna zaleta ASP.NET Core. Ale czy faktycznie kiedyś .NET Core może stać się światowym standardem na miarę Javy? Nie sądzę, że tak się stanie, dopóki ewangeliści będą siać propagandę o „gotowości do zastosowania produkcji” dla wynalazków, które nadają się co najwyżej do prezentacji na konferencjach. Propaganda jednak się sprawdza. Ja natomiast zachęcony entuzjazmem innych siadam i chcę coś odpalić, a część rzeczy po prostu jeszcze nie działa, lub nie działa zgodnie z założeniam.
  • Kod pośredni, zatem jak by nie było – kompilowany, daje szereg zalet – oprócz technicznych, mamy choćby częściową ochronę własności intelektualnych – to dla mnie naprawdę istotne.
  • Aplikacje ASP.NET Core to na razie web, ale niebawem międzyplatformowe UI dla desktop – zatem ogromne możliwości dla programisty.
  • Niestety ciągłe zmiany podejścia przez Microsoft sprawiają wrażenie, jakby nie mieli jasnej wizji rozwoju. Każda nowa wersja przynosi nowe podejście i programista jest zmuszony do ciągłego grzebania w marnej jeszcze dokumentacji.
  • Aby napisać prosty projekt, trzeba się umęczyć, bowiem to samo w PHP, Railsach czy Django robi się w minutę, czasem jednym poleceniem. Oczywiście może to wynikać z mojego braku doświadczenia w ASP.NET Core. Zresztą pewnie pisząc niniejszy artykuł pewnie popełniłem jakieś błędy merytoryczne. Odnoszę wrażenie, że .NET Core i C# jest bardzo wrażliwe na błędy – konfiguracyjne, wynikające z zależności, kodu (np. silne typowanie zmiennych przez EF), ale także nie można wykluczyć, że błędy frameworka.
  • Kompilacja trwa długo nawet w przypadku małych projektów. A to dla mnie istotna wada, bowiem gdy popełnię mały błąd, trzeba wszystko przekompilować i ponownie tracę czas. W przypadku opisanej aplikacji kompilacja i uruchomienie przeglądarki trwa nawet kilkanaście sekund. Dla porównania to samo w CakePHP – natychmiast – wystarczy odświeżyć stronę, Ruby czy Python – restart serwera to może sekunda.
  • Jeśli wierzyć deweloperom .NET, w miarę rozwoju projektu łatwiej go utrzymać i skalować niż w przypadku użycia innych technologii, lecz ja nie piszę ogromnych aplikacji. Faktycznie – w ASP .NET Core długo trwa przygotowanie środowiska, zaś samo programowanie jest już podobnie jak w innych technologiach, jednakże mam wątpliwości, czy tego typu podejście jest dobre na deadline’y freelancerów.
  • Uwaga może nie dotyczy samego .NET, ale ekosystemu – w Mac OS brak jest MS SQL Server (na Linuxa już jest). Mamy za to darmowe SQL Operations Studio – jakąś namiastkę MS SQL Server Management dla Windows, Linux oraz Mac OS i można podłączyć się do innej maszyny.

A może macie  doświadczenie w ASP.NET Core w Linux lub Mac OS i potraficie wskazać mi błędy, porady, jakieś wskazówki do ww artykułu? A może ktoś z Was próbował przejść na .NET Core z innych środowisk uznał, że nie warto? Piszcie w komentarzach – każdy głos mile widziany.

Przypisy

  1. Dalej – VSC.
  2. Więcej: https://pl.wikipedia.org/wiki/OOTB

Bibliografia

  1. Wprowadzenie do platformy ASP.NET Core, https://docs.microsoft.com/pl-pl/aspnet/core/?view=aspnetcore-2.1 (dostęp z dnia 11.07.2018).

1340total visits,15visits today

Tagi , , , , .Dodaj do zakładek Link.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

1 + = 9

This site uses Akismet to reduce spam. Learn how your comment data is processed.