Dokumentowanie własnego API automatem – co to Swagger?

Dokumentowanie własnego API automatem – co to Swagger?

Wstęp

Któż z nas nie kocha pisania dokumentacji? 😉 No właśnie. Nikt tego nie chce robić, ale każdy chciałby mieć dokumentację do zewnętrznych systemów. Niestety tworzenie takich materiałów jest po prostu upierdliwe… Ale nie musi. W tym artykule pokażę Ci jak szybko i prosto zrobić bardzo funkcjonalną dokumentację dla własnego API.

Co to Swagger?

Swagger to narzędzie, które magicznie skanuje Twoje API i tworzy stronę, na której ładnie opisuje wszystkie końcówki. Co więcej, umożliwia testowanie takiego API na żywym organizmie. To jest dokumentacja w pełni interaktywna.

Wszystko zrobisz w Visual Studio – nie musisz otwierać żadnego innego edytora. Zaczynamy.

Dodawanie Swaggera do projektu

Swagger jest tak fajnym narzędziem, że Microsoft pozwala na dodanie go już podczas tworzenia samego projektu. W oknie konfiguracji możesz wybrać, czy go używać, czy nie.

To oczywiście najprostsza droga do dodania Swaggera. Ale być może jest tak, że masz projekt, w którym nie zaznaczyłeś tej opcji. Tak też się da.

Dodawanie Swaggera ręcznie

Pobierz NuGet:

Install-Package Swashbuckle.AspNetCore.Swagger

Teraz musisz skonfigurować Swaggera.

Dodaj go przy rejestracji serwisów:

builder.Services.AddControllers();
builder.Services.AddSwaggerGen();

A podczas konfiguracji pipeline dodaj:

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

Tutaj mała uwaga. Być może pracujesz nad API, które będzie wystawiane zewnętrznie dla klientów. W takim przypadku prawdopodobnie nie powinieneś dodawać Swaggera tylko w środowisku deweloperskim ale produkcyjnie też.

I teraz małe wyjaśnienie:

  • builder.Services.AddSwaggerGen(); – rejestruje serwisy potrzebne do obsługi Swaggera
  • app.UseSwagger(); – to podstawowa obsługa
  • app.UseSwaggerUI(); – dodaje do Twojego API specjalną stronę, na której wszystko jest ładnie opisane, a w dodatku można testować.

To tyle, jeśli chodzi o podstawową konfigurację.

Przykładowy projekt

Swaggera najlepiej pokazać na przykładzie. W związku z tym przygotowałem prostą solucję, składającą się z dwóch projektów. SwaggerDemo to jest nasze API, SwagerDemo.Models to projekt przechowujący modele aplikacji. Specjalnie są zrobione dwa projekty, żeby Ci pokazać coś więcej. Cały gotowy kod możesz sobie sklonować z GitHuba: https://github.com/AdamJachocki/SwaggerDemo

Jeśli nie chcesz korzystać z mojego projektu, po prostu dodaj Swaggera do swojego (tak jak to opisane wyżej).

Możesz teraz uruchomić projekt API. Ważne, żeby API otwierało przeglądarkę. Jeśli Twoje nie otwiera, możesz zmodyfikować plik Properties/launchSettings.json, zmieniając wartość zmiennej launchBrowser na true. Możesz też automatem otworzyć stronę Swaggera, dodając do lauchSettings.json zmienną launchUrl:

"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7090;http://localhost:5090",
"environmentVariables": {
  "ASPNETCORE_ENVIRONMENT": "Development"

Jeśli dodawałeś Swaggera automatycznie (lub zmodyfikowałeś launchSettings.json jak wyżej), prawdopodobnie od razu pokazuje Ci się jego strona. Jeśli nie, doklep w przeglądarce końcówkę swagger. Przykładowo, jeśli adres Twojego API to http://localhost:5001, przejdź na: http://localhost:5001/swagger.

Tak mniej więcej wygląda podstawowa dokumentacja wygenerowana Swaggerem. Osobno widzisz każdy kontroler, w kontrolerze kolekcję endpointów, każdy rodzaj endpointa (POST, GET, DELETE) ma swój kolor. Jeśli rozwiniesz endpoint, zobaczysz dokładnie jakie przyjmuje dane, co zwraca i będziesz mógł go wywołać (przycisk Try it out z prawego, górnego narożnika). Swagger automatycznie rozpoznaje dane wchodzące:

Niemniej jednak, zgodzisz się że to słaba dokumentacja i właściwie niczego nie mówi. Poza tym, że pozwala Ci wysłać żądanie po kliknięciu przycisku Try it out. Ale spokojnie. Zaraz się tym zajmiemy.

Dokumentacja generowana z komentarzy

Każdy endpoint możesz dokładnie opisać za pomocą komentarzy dokumentujących, np:

/// <summary>
/// Pobiera użytkownika po przekazanym id
/// </summary>
/// <param name="id">Id użytkownika</param>
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
    User testUser = new User
    {
        Email = "test@example.com",
        Id = 1,
        Name = "Test"
    };

    return Ok(testUser);
}

Tekst jaki wpisałeś w <summary> pojawi się jako opis konkretnego endpointa. Natomiast opisy parametrów <param> pojawią się przy parametrach. Jednak żeby to zadziałało, musisz dokonfigurować projekt API.

Konfiguracja projektu

W pliku projektu dodaj:

<GenerateDocumentationFile>True</GenerateDocumentationFile>

Możesz też zrobić to z poziomu ustawień projektu: Build -> Output -> Documentation file:

To ustawienie sprawi, że VisualStudio podczas budowania aplikacji, utworzy specjalny plik XML z metadanymi dokumentacji. Plik będzie nazywał się tak jak projekt, np: SwaggerDemo.xml. I domyślnie tworzy się w katalogu wynikowym.

To ustawienie jednak spowoduje również mały efekt uboczny. Podczas budowania aplikacji otrzymasz warningi CS1591, mówiące o tym, że są publiczne metody, które nie mają komentarzy dokumentujących. My tutaj dokumentujemy tylko metody w kontrolerach, aby Swagger mógł zadziałać. Jeśli nie dokumentujesz wszystkich metod publicznych, możesz ten warning wyłączyć, dodając do pliku projektu:

<NoWarn>$(NoWarn);1591</NoWarn>

Mój plik projektu API wygląda teraz tak:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>disable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <GenerateDocumentationFile>True</GenerateDocumentationFile>
	<NoWarn>$(NoWarn);1591</NoWarn>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\SwaggerDemo.Models\SwaggerDemo.Models.csproj" />
  </ItemGroup>

</Project>

Konfiguracja Swaggera

Swagger odczytuje opisy właśnie z tego pliku XML. Trzeba mu to tylko powiedzieć. Robisz to, podczas konfigurowania Swaggera w kodzie przy konfiguracji serwisów:

builder.Services.AddSwaggerGen(o =>
{
    var assemblyName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
    var docFile = Path.Combine(AppContext.BaseDirectory, assemblyName);
    o.IncludeXmlComments(docFile);
});

Tutaj nie ma żadnej magii. Kluczową instrukcją jest IncludeXmlComments, gdzie w parametrze podaję pełną ścieżkę do utworzonej automatycznie dokumentacji xml. Czyli pobieram ścieżkę wykonywanego pliku, pobieram nazwę projektu i łączę to.

Teraz dokumentacja Swaggerowa wygląda już tak:

Opisywanie odpowiedzi

Swaggerowi możesz powiedzieć jeszcze, jakie endpoint generuje odpowiedzi i kiedy:

/// <summary>
/// Pobiera użytkownika po id
/// </summary>
/// <param name="id">Id użytkownika</param>
/// <response code="200">Zwraca znalezionego użytkownika</response>
/// <response code="404">Nie znaleziono takiego użytkownika</response>
/// <response code="500">Wewnętrzny błąd serwera</response>
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
    User testUser = new User
    {
        Email = "test@example.com",
        Id = 1,
        Name = "Test"
    };

    return Ok(testUser);
}

Teraz strona Swaggera wygląda tak:

Patrząc na taką dokumentację nadal nie wiesz, jakie dane zwróci endpoint, jeśli zapytanie zakończy się sukcesem (kod 200). Możesz oczywiście wywołać tę końcówkę z poziomu Swaggera i otrzymasz wszystkie dane pobrane z API:

Jednak jest pewien sposób…

Opisywanie zwracanego modelu

Możesz pokazać Swaggerowi zwracany model:

[Route("api/[controller]")]
[ApiController]
[Produces("application/json")]
public class UsersController : ControllerBase
{
    /// <summary>
    /// Pobiera użytkownika po id
    /// </summary>
    /// <param name="id">Id użytkownika</param>
    /// <response code="200">Zwraca znalezionego użytkownika</response>
    /// <response code="404">Nie znaleziono takiego użytkownika</response>
    /// <response code="500">Wewnętrzny błąd serwera</response>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(User), 200)]
    public IActionResult GetById(int id)
    {
        User testUser = new User
        {
            Email = "test@example.com",
            Id = 1,
            Name = "Test"
        };

        return Ok(testUser);
    }
}

Tutaj zrobiłem dwie rzeczy. Na poziomie kontrolera powiedziałem, jaką odpowiedź kontroler zwraca (json). Co nie jest wymagane, ale lepiej wygląda w Swaggerze. No i oczywiście klienci Twojego API nie mają żadnych wątpliwości co do rodzaju zwrotki. W innym przypadku Swagger pokaże combobox z możliwością wyboru typu zwrotki.

Ważniejsza jednak rzecz jest na poziomie samego endpointa – atrybut ProducesResponseType. W parametrach pokazuję jaki typ jest zwracany przy jakim kodzie. Różne kody mogą zwracać różne typy modeli. Teraz Swagger wygląda tak:

Jak widzisz Swagger pokazuje teraz szablon zwracanego modelu.

Opisywanie pól modelu

W rzeczywistości modele bywają bardziej skomplikowane niż ten powyżej. A ich pola nie opisują się tak ładnie. Możemy Swaggerowi opisać dokładnie każde pole modelu. Jak? Również za pomocą komentarzy dokumentujących. Tym razem na poziomie konkretnego modelu:

public class User
{
    /// <summary>
    /// Id użytkownika
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// Imię i nazwisko użytkownika. Uwaga! Pole może być puste
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// E-mail użytkownika
    /// </summary>
    public string Email { get; set; }
    /// <summary>
    /// Hasło użytkownika. Zawsze puste, gdy pobieramy rekord.
    /// </summary>
    public string Password { get; set; }
}

Co się stanie, gdy odpalimy teraz Swaggera? Zupełnie nic 🙂

Dlatego też stworzyłem dwa projekty – jeden api, drugi dla modeli.

Przypominam, że Swagger opisy odczytuje z pliku dokumentacji (xml) tworzonego przez Visual Studio. O ile projekt API został ładnie ustawiony, to projekt z modelami nie ma takiej konfiguracji. Musimy ją więc dodać. Do projektu z modelami dodaj znane już elementy:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>disable</Nullable>
	<GenerateDocumentationFile>True</GenerateDocumentationFile>
	<NoWarn>$(NoWarn);1591</NoWarn>
  </PropertyGroup>

</Project>

Teraz jeszcze tylko musisz Swaggerowi powiedzieć, skąd ma ten dokument zaczytać. To też już robiliśmy. Podczas konfiguracji Swaggera trzeba tylko dodać kolejny plik:

builder.Services.AddSwaggerGen(o =>
{
    var assemblyName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
    var docFile = Path.Combine(AppContext.BaseDirectory, assemblyName);
    o.IncludeXmlComments(docFile);

    var modelsAssemblyName = typeof(User).Assembly.GetName().Name + ".xml";
    var modelsDocFile = Path.Combine(AppContext.BaseDirectory, modelsAssemblyName);
    o.IncludeXmlComments(modelsDocFile);
});

Tutaj, żeby nie wpisywać na sztywno nazwy projektu, posłużyłem się jakąś klasą, która występuje w projekcie z modelami. Traf chciał, że padło na klasę User. Generalnie wybrałem pierwszą lepszą. Chodziło o to, żeby refleksja zwróciła nazwę projektu. Reszta jest taka sama jak wyżej: IncludeXmlComments i wio.

Teraz Swagger wygląda tak:

Pamiętaj, że żeby zobaczyć opisy pól modelu, musisz kliknąć na Schema.

Swagger i wersjonowanie API

Często nasze API są wersjonowane. Swagger niestety nie ogarnia tego domyślnie. Jest kilka sposobów, żeby to zadziałało. Ja Ci pokażę jeden z nich – moim zdaniem najbardziej prawilny.

Jak to działa?

Słowem wstępu, Swagger działa tak, że używa mechanizmu dostarczanego przez Microsoft: EndpointsApiExplorer. Nie musisz tego dodawać ręcznie, to już dodaje Swagger podczas rejestrowania swoich serwisów.

ApiExplorer skanuje Twoje API i zwraca informacje o nim, a Swagger za jego pomocą buduje swoje pliki „map”.

Przy tym podejściu musisz zapewnić, że wersjonujesz API tak jak napisałem tutaj. Głównie chodzi o trzymanie kontrolerów dla różnych wersji w różnych namespace.

Krok 1 – stworzenie konwencji

Na początek musimy utworzyć konwencję, która odpowiednio pogrupuje kontrolery. Stwórz taką klasę:

public class GroupingByNamespaceConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        var controllerNamespace = controller.ControllerType.Namespace;
        var apiVersion = controllerNamespace.Split(".").Last().ToLower();
        if (!apiVersion.StartsWith("v")) 
            apiVersion = "v1";

        controller.ApiExplorer.GroupName = apiVersion;
    }
}

Zadaniem tej klasy jest odpowiednie zgrupowanie kontrolera (dodanie atrybutu GroupName). To grupowanie jest używane tylko przez ApiExplorer, czyli nie ma żadnego znaczenia dla działającego kodu. Zapamiętaj – tylko dla dokumentacji. Teraz trzeba tą konwencję zarejestrować podczas rejestracji serwisów:

builder.Services.AddControllers(o =>
{
    o.Conventions.Add(new GroupingByNamespaceConvention());
});

Krok 2 – konfiguracja dokumentacji Swaggera

Teraz musimy skonfigurować dokumentację dla każdej wersji. Robimy to podczas konfiguracji Swaggera:

builder.Services.AddSwaggerGen(o =>
{
    o.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "Wersja 1",
        Version = "v1"
    });

    o.SwaggerDoc("v2", new OpenApiInfo
    {
        Title = "Wersja 2",
        Version = "v2"
    });
});

Dodałem tutaj dwie wersje. Na koniec trzeba jeszcze je dodać podczas konfiguracji middleware:

app.UseSwagger();
app.UseSwaggerUI(o =>
{
    o.SwaggerEndpoint("/swagger/v1/swagger.json", "Wersja 1");
    o.SwaggerEndpoint("/swagger/v2/swagger.json", "Wersja 2");
});

Ważne, żeby nazwa przekazana w SwaggerEnpoint (Wersja1, Wersja2) była spójna z tytułem skonfigurowanym w SwaggerDoc.

Krok trzeci – aktualizacja kontrolerów

Na koniec już tylko musisz zaktualizować kontrolery, żeby powiedzieć im, którą wersję API wspierają. Prawdopodobnie będą sytuacje, że pomiędzy pierwszą i drugą wersją API zmieni Ci się tylko część kontrolerów. Wystarczy, że dodasz do nich atrybuty ApiVersion:

[Route("api/[controller]")]
[ApiController]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class ItemsController : ControllerBase
{

}

Ułatwienia

Istnieje NuGet, który ułatwia konfigurowanie wersji w Swaggerze. Jednak komentarz autora (który przytaczam fragmentami niżej) mi daje taką myśl: „Wstrzymaj konie i poczekaj na nową wersję”. Ten NuGet to: Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer, jednak nie daj się zmylić – nie ma za wiele wspólnego aktualnie z Microsoftem:

Projekt rozpoczął się jako eksperyment myślowy jak wziąć pomysły stojące za wersjonowaniem API (zwłaszcza RESTowego) i zaimplementować je w praktyczny sposób (…). Rozwój (…) różnych projektów w Microsoft zajął około dwóch lat, ale w końcu powstał ogólny wzorzec i framework. 6 lat temu (2016 – przyp. tłumacz) przeniosłem to do społeczności open source, żeby rozwijać dalej i szczerze – dla mojego własnego egoistycznego użytku do projektów poza Microsoftem. To, że projekt stał się taki popularny, przerosło moje najśmielsze oczekiwania.

Decyzja, żeby przenieść projekt na Microsoftowy GitHub była głównie podyktowana open source’ową polityką firmy. Pomimo powszechnego przekonania, nie jestem i nigdy nie byłem częścią teamu od AspNetCore (…). Ten projekt nigdy w żaden sposób nie był oficjalnie wspierany. Pomimo, że pojawiło się kilku zewnętrznych kontrybutorów, głównie utrzymywałem go sam. W 2021 (…) zdecydowałem się opuścić Microsoft (…). Próbowałem zachować projekt i przekazać go, jednak pojawiło się wiele wyzwań. Zajęło to kilka miesięcy, ale ostatecznie uznałem, że najlepszym będzie przeniesienie projektu z organizacji Microsoft do .NET Foundation (…).

Pojawiło się kilka nowych problemów, m.in. nazwa, która wskazuje, że projekt jest zarządzany przez Microsoft (…). Chciałem zrobić fork projektu i rozpocząć nowy, jednak mogłoby to wprowadzić zamieszanie w społeczności (…).

Drugi problem to identyfikatory pakietów NuGet. Zasugerowano, że po prostu wyślę zawiadomienie, że identyfikator się zmieni. Jednak po 100 milionach pobrań stwierdziłem, że jest to niedopuszczalne. Zajęło to wiele miesięcy aby wyśledzić odpowiednich interesariuszy NuGet, aby rozpocząć proces, ale identyfikatory pakietów zostały teraz przeniesione do zespołu api-versioning z dotnetfoundation. Jeśli zastanawiasz się, dlaczego nie było żadnych aktualizacji od dłuższego czasu, to właśnie dlatego. Teraz mam trochę więcej kontroli nad pakietem i aktualizacje mogą znów się pojawiać. Jednak są z tym związane limity. Nowe funkcje nie mogą pojawiać się pod szyldem Microsoft(…). Zacząłem nawet prace nad nową wersją, która zaczynałaby się prefixem Asp.Versioning.* (…).

Krótko mówiąc – projekt powinien mieć jakieś aktualizacje do wersji 5.*. Jednak niczego więcej po nim nie można się spodziewać. A jego klon gdzieś kiedyś się pojawi.


To tyle, jeśli chodzi o dokumentowanie API. Jak widzisz, nie musi to być tak nudne, jak się wydaje. A i musisz przyznać, że dla klienta taka interaktywna dokumentacja ma dużo większą wartość niż tabelka w Wordzie. Spróbuj sam i zobacz, jak to jest. Co więcej, Swagger posługuje się standardem OpenAPI 3.0, więc możesz to sobie zaimportować nawet do PostMana! 🙂

Dzięki za przeczytanie artykułu. Jeśli czegoś nie zrozumiałeś lub znalazłeś jakiś błąd, koniecznie podziel się w komentarzu. A jeśli znasz kogoś, komu ten artykuł się zdecydowanie przyda, udostępnij mu go 🙂

Podziel się artykułem na:
Rozmowa z telefonem przez terminal

Rozmowa z telefonem przez terminal

Wstęp

Tworząc aplikacje na telefony, czasem pojawia się pytanie „Jak usunąć plik z Androida” albo „Gdzie jest AppData na Androidzie”. Na szczęście wraz z Visual Studio mamy dostępne takie narzędzie jak ADB (Android Debug Bridge), które pozwala na wywoływanie komend shellowych bezpośrednio na telefonie.

Jestem rootem…

Przede wszystkim musisz uruchomić narzędzie adb z opcją root’a. Uruchom adb z menu Visual Studio: Tools -> Android -> Android ADB Command Prompt. Oczom Twoim ukaże się piękne okienko konsolowe. Ale to nie jest zwykła konsola, ta wersja ma dostęp do adb. Teraz, aby uruchomić adb w trybie root’a, wpisz poniższe polecenie:

adb root

W tym momencie możesz dostać kilka odpowiedzi:

  • nie można tego zrobić ze względu na jakiś błąd, np: „adb: unable to connect for root: no devices/emulators found” – co znaczy, że nie znaleziono żadnego urządzenia – wtedy po prostu uruchom emulator lub podłącz fizyczne urządzenie do kompa
  • serwer już chodzi jako root („adbd is already running as root”)
  • zrestartowano serwer w trybie roota (w tej sytuacji możesz nie otrzymać żadnego komunikatu)

Jeśli nie możesz zrootować telefonu

Nie każdą wersję emulatora można zrootować. Te z opcją GooglePlay z jakiegoś powodu nie są rootowalne. Dlatego też, jeśli otrzymałeś taki komunikat, musisz się upewnić, że nie masz w emulatorze opcji Google Play. Z menu Visual Studio wybierz: Tools -> Android -> Android Device Manager

Z tego managera wyedytuj emulator, którego chcesz używać

Android Device Manager

Wszystko rozbija się o to, żeby telefon nie miał opcji Google Play. Pozostaw to puste:

Gdy odznaczysz tę opcję i klikniesz OK, manager zainstaluje nowe urządzenie bez Google Play Store. Takie urządzenie będziesz już mógł rootować za pomocą komendy adb root tak jak wyżej.

Połączenie z telefonem

Gdy już udało Ci się uruchomić serwer adb w trybie roota, możesz teraz „połączyć się” z jego shellem. Po prostu wpisz polecenie:

adb shell

Jeśli masz kilka urządzeń, będziesz musiał podać nazwę konkretnego. Najpierw pobierz te nazwy poleceniem:

adb devices -l

To polecenie pokaże Ci pełną listę podłączonych urządzeń, np:

List of devices attached
emulator-5554 device product:sdk_gphone_x86 model:Android_SDK_built_for_x86 device:generic_x86 transport_id:5

Teraz możesz połączyć się z konkretnym urządzeniem, podając jego nazwę:

adb -s emulator-5554 shell

lub jego transport_id:

adb -t 5 shell

Jeśli wszystko poszło ok, powinieneś zobaczyć taką lub podobną zachętę:

generic_x86:/ #

UWAGA!

Jeśli zamiast hasha (#) widzisz dolar ($), to znaczy, że nie jesteś zalogowany jako root i coś poszło nie tak. Sprawdź, czy wykonałeś wszystkie kroki jeszcze raz.

W tym momencie możesz bawić się shellem na swoim emulatorze.

Jak usunąć plik?

Jeśli znasz chociaż troszeczkę polecenia Linuxa… liznąłeś go kiedykolwiek, to już jest dobrze. Jeśli kojarzysz polecenia takie jak ls, czy cd, to nie powinieneś mieć więcej pytań. Po prostu czuj się jak na Linuchu. Jeśli jednak jesteś zielony w te klocki, to lepiej żebyś ogarnął podstawy pracy z konsolą Linuxa. Kilka podstawowych poleceń w zupełności wystarczy:

  • ls – skrót od LIST, a więc listuje wszystkie „foldery” będące na tym poziome
  • cd – tak jak w Windows – Change Directory – przechodzi do wskazanego „folderu”
  • rm – usuwa podany plik

I to wszystko… Hulaj dusza, piekła nie ma!

Gdzie pliki z mojego programu?

Pliki programu powinieneś umieszczać w odpowiednim katalogu z Environment.SpecialFolder. W taki sposób też prosto możesz poznać dokładną ścieżkę do takiego katalogu:

string targetDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); //tutaj przykład do LocalAppData

Jeśli masz problem lub znalazłeś błąd w artykule, podziel się w komentarzu

Podziel się artykułem na:
Visual Studio 2022 – pierwsze spojrzenie

Visual Studio 2022 – pierwsze spojrzenie

Wstęp

Zazwyczaj tego nie robię. Gdy wychodzi nowy Visual, zazwyczaj czekam około pół roku zanim go zainstaluję i zacznę używać. Po prostu chcę uniknąć głupich problemów „wieku dziecięcego”. Tym razem jednak było inaczej. Z jakiegoś powodu nie mogłem doczekać się Visual Studio 2022. Zainstalowałem sobie nawet wersję Preview, ale w sumie nie używałem jej. W końcu wyszło… Poczułem silną wewnętrzną potrzebę przetestowania tego ustrojstwa i jak najszybszego używania go… W tym artykule dzielę się swoimi pierwszymi spostrzeżeniami. Opisuję wersję 17.0.0 Community

Sprzęt

Być może sprzęt, na którym go testuje ma jakieś znaczenie (na pewno ma w pewnych sytuacjach), dlatego postanowiłem przedstawić Wam go

  • Sprzęt: HP Pro Book 450 G3
  • System operacyjny: Windows 10 19042
  • Procesor: Intel Core i3-6100U 2.30 GHz, 2 rdzenie, 4 logiczne procesory
  • RAM: 16 GB
  • Ekran 17″

Testowałem też na innym kompie – 2 spore monitory (z czego jeden 4K) i 16 rdzeni (dokładnej konfiguracji nie pamiętam)

Instalacja

Tutaj nie ma nowości. Pobrany instalator musiał najpierw ściągnąć kilka rzeczy, co zajęło mu około 30 sekund. Następnie uruchomił się już znany Visual Studio Installer, w którym wybrałem takie składniki:

  • ASP.NET Core, ASP.NET
  • Node.js
  • Aplikacje mobilne (Xamarin)
  • Programowanie aplikacji klasycznych .NET
  • Magazynowanie i przetwarzanie danych
  • Programowanie rozszerzeń Visual Studio

Niektóre „podskładniki” jak np. środowisko uruchomieniowe .NET 5 miałem już zainstalowane, więc czas instalacji będzie nieco krótszy.

W każdym razie, wszystko zajęło 11,12 GB. A całkowity czas instalacji to około 11 minut. Całkiem nieźle, biorąc pod uwagę, że AKTUALIZACJA VS2019 z wersji 16.11.5 na 16.11.6 zajęła prawie 7 i pół minuty.

Otwieranie solucji

Widziałem jak MS chwalił się szybkością otwierania solucji z ponad 100 projektami. Na pokazie trwało to naprawdę szybko. Żeby niczego nie zaburzyć, postanowiłem pierwsze otwarcie przeprowadzić bez żadnego kodu. Podejrzewam, że podczas pierwszego uruchamiania VS robi więcej rzeczy niż zazwyczaj.

Otwarcie solucji z 36 projektami trwało 50 sekund. Przy czym otwarcie tej samej solucji na VS2019 trwało 45 sekund. ALE! Najwidoczniej VS2022 optymalizuje sobie w jakiś sposób pracę. Drugie otwarcie tej samej solucji w VS2022 (po restarcie środowiska) zajęło już tylko 30 sekund. Więc faktycznie coś w tym jest.

Wygląd

Wygląd różni się nieco od VS2019. Są inne ikonki, inne czcionki… Wszystko to ponoć ma sprawić przyjemniejszą i bardziej skupioną pracę. Myślę, że ocena tego jest dość indywidualna, a ja jeszcze nie spędziłem przy tym środowisku tyle czasu, żeby móc to ocenić.

Co się jednak rzuca w oczy na początek, to czcionka w edytorze kodu. I tu mam mieszane uczucia. Na dużym monitorze 4K wygląda to całkiem nieźle. Natomiast na moim laptopie z ekranem 17″… było mi jakby za ciasno. Dlatego zmieniłem na starą Consolas. Ale to też kwestia dość indywidualna.

Pierwszy problem…

Na jednym komputerze wszystko poszło podejrzanie sprawnie. Jednak na drugim nie mogłem uruchomić aplikacji .NetCore WPF w środowisku. Ciągle dostawałem błąd:

The target process exited without raising a CoreCLR started event.Ensure that the target process is configured to use .NET Core. This may be expected if the target process did not run on .NET Core

Przeszukałem Internety wzdłuż i wszerz i dupa. Restarty, reinstalacje .NetCore, odinstalowywanie starszych wersji… nic nie dawało rady. Wygląda na to, że podczas pierwszej instalacji czegoś nie dopatrzyłem, co było potrzebne dla mojej aplikacji. Gdy doinstalowałem kilka rzeczy później nadal nic nie działało. Musiałem ostatecznie wybrać opcję „Napraw” z VsInstallera. I wtedy wszystko zaczęło magicznie działać.

Z czego wynika ten problem? W pierwszej wersji VS2019 był to faktycznie jakiś problem ze środowiskiem. Tutaj ciężko mi powiedzieć. Być może środowisko nie ogarnęło czegoś w 100% podczas doinstalowywania modułów.

Hot Reload

Podczas prezentacji niesamowicie jarali się mechanizmem HotReload, który ponoć w tej wersji jest przełomowy. I faktycznie – pokazywali Hot Reload w projekcie w C++, co mnie zupełnie zbiło z tropu. Postanowiłem to sprawdzić na jakimś projekcie MFC…

C++ i MFC

No niestety. Wygląda na to, że MFC jest zbyt starą technologią, żeby wspierało HotReload. Niestety można się było tego spodziewać. Więcej nie testuję C++, chociaż na prezentacji faktycznie to działało (oczywiście nie pokazywali tego na MFC, tylko na jakiejś prostej gierce).

WPF

Na pierwszy rzut oka naprawdę bardzo fajnie to działa. Można robić zmiany zarówno w XAML jak i w kodzie C# (!) i HotReload naprawdę daje radę. Co więcej, nie trzeba nawet zapisywać tych zmian! Wszystko dzieje się na bieżąco. Można zmieniać nawet style, a także user controlsy, co kiedyś było upierdliwe i to działa… ale… no właśnie.

Podczas zmian w globalnych stylach w pliku App.xaml coś się pieprzy i zmiany nie są widoczne. Co więcej, cała aplikacja jakby znalazła się w jakimś dziwnym stanie zawieszenia. Chociaż MS sam mówił, że przy niektórych zmianach w kodzie trzeba jednak zrestartować aplikację. Może ma to jakiś związek.

Co więcej, świetne jest okienko Preview (Debug -> Windows -> XAML Live Preview). Pokazuje aktualne okno uruchomionej aplikacji. Świetnie się sprawdza w przypadku jednego monitora, bo nie trzeba przełączać się między Visualem i aplikacją. Okienko Preview jest po prostu zadokowane. Zmiany są widoczne zarówno w tym oknie, jak i w aplikacji. Okienko preview ma też kilka dodatkowych rzeczy w stylu linijek znanych z programów graficznych. Bardzo to może wspomóc ustawianie elementów.

Dodatkowo jest w stanie pokazać w jakim pliku znajduje się jak element:

Okienko XAML Live Preview wraz z fragmentem XAML

Ogólne wrażenie: PLUS. Gdyby nie ten problem z plikiem App.xaml, byłbym niesamowicie zachwycony. Ale nadal – czapki z głów. Naprawdę dobrze działający mechanizm.

Xamarin

HotReload w Xamarinie zazwyczaj działało mi „od święta”. Głównie jednak nie działało, co było bardzo frustrujące i zabierało mnóstwo czasu. Dlatego z wielkim polskim przekąsem na twarzy podszedłem do tego tematu…

No cóż… Dupy nie urywa. HotReload w Xamarinie „potrafi” działać w dwóch trybach (od pewnej wersji). Może odświeżać tylko to, co się zmieniło lub całą stronę.

Okienko Preview udało mi się pokazać tylko w trybie „odświeżania samych zmian”. Natomiast w trybie odświeżania całej strony w ogóle nie działało. Ale to nie jest najgorsze. Tryb odświeżania tylko zmian w ogóle nie chciał działać. Udało się za to uruchomić HotReload w trybie odświeżania całej strony. Nie działa to jednak tak super jak w WPF. Tutaj jest jeszcze trochę pracy do zrobienia.

Jednak, podczas moich testów, HotReload w trybie odświeżania całego ekranu działał cały czas.

Ogólne wrażenie: mieszane… bardziej negatywne. Coś tam działa. Ale kiedy przestanie?

ASP.NET MVC

Niestety tutaj nie działa. Ale MS pisze o tym na swoich stronach. Więc tutaj trzeba posługiwać się starymi metodami. Podobnie jak…

BLAZOR!

Technologia, w której ostatnio się podkochuję. Obiecali, k… obiecali! Obiecali, że będzie Hot Reload! No i jest… Podobno. Gdy używa się .NET6. Aplikacja w Blazor, którą gdzieś tam sobie robię na boku jest na .NET5 i ma dla mnie aktualnie dość niski priorytet. W końcu zmigruję ją do .NET6 i wtedy sprawdzę. Póki co… Smutek…

Designer

Tutaj właściwie napiszę tylko o WPF. W Xamarinie standardowo nie ma takiego pojęcia jak designer, w corowych aplikacjach webowych też nie. Designer w WinForms właściwie się nie zmienił, dlatego opisuję to dla WPF.

Designer w WPF zyskał kilka nowych i fajnych elementów. Przede wszystkim można zmienić niektóre właściwości kontrolki, zaznaczając ją, a następnie klikając żaróweczkę, która się pojawia:

Może i pierdoła, ale naprawdę ułatwia życie.

Ale największy życioułatwiacz dla mnie to element „d” w XAML. Na pewno nie raz miałeś taką sytuację, że musiałeś zaprojektować jakiś element znajdujący się na jakiejś liście. I co wtedy się robi? Trzeba stworzyć jakieś fake’owe dane, żeby elementy były widoczne na liście w design time i generalnie potem trzeba pamiętać, żeby powrócić do prawdziwych danych… Nie jest to zbyt eleganckie rozwiązanie.

Tutaj mamy coś takiego jak wersja w design time (stąd „d”). Kod powie więcej niż 1000 słów:

<TextBlock Text="{Binding Name}" 
           d:Text="Nazwa elementu"
           FontWeight="{Binding Modified, Converter={StaticResource BoolToFontWeight}}"
           d:FontWeight="Bold"/>

Jak widzisz mamy tutaj właściwości Text i d:Text. FontWeight i d:FontWeight. Te prawdziwe właściwości (Text i FontWeight) działają normalnie – w runtime, czyli gdy aplikacja jest uruchomiona. Jeśli jednak jesteś w design time (aplikacja jest projektowana), działają właściwości z elementem d:. Czyli wszystko, co ma d: zostanie użyte w czasie projektowania aplikacji. Dla mnie jest to niesamowita opcja.

Wyszukiwanie plików

Zawsze niesamowicie denerwowało mnie wyszukiwanie plików w solution explorerze. Działało to bardzo topornie, a czasami pokazywało strasznie długą listę, na której trzeba było znaleźć to, co się chce. Właściwie pozostawało używanie thirdparty pluginów…

W wersji 2022 wreszcie działa to lepiej. Szukanie jest zdecydowanie szybsze i pokazuje wyniki, które bardziej pasują do tego, co chcesz znaleźć.

Podpowiedzi w kodzie – sztuczna inteligencja

Nie mówię tutaj o Intellisense. W tej wersji wprowadzili sztuczną inteligencję, która podpowiada Ci, co powinieneś napisać. Niedługo dojdzie do tego, że będziemy programować wciskając tylko tabulator 😉

Działa to tak, że Microsoft przeanalizował mnóstwo kodów, przede wszystkim na GitHubie i na tej podstawie nauczył sieć neuronową… programowania. To oczywiście zbyt duże słowo. Ale faktycznie – sztuczna inteligencja w jakiś sposób rozpoznaje kontekst w jakim się znajduje i w jakiś szatański sposób potrafi przewidzieć, co chcesz napisać. Testowałem to na swoich kodach. W miejscach, gdzie klasy były raczej unikalne i konteksty raczej też. No nie były to miejsca „typowe”. I ku mojemu wielkiemu zdziwieniu – działa całkiem nieźle. I nawet nie przeszkadza.

To co widzisz na obrazku powyżej to oczywiście dość „typowe” miejsce, ale wierz mi, że mechanizm jest naprawdę ciekawy. Podczas moich testów kilka razy naprawdę mnie zaskoczył.

MAUI

A gdzie MAUI? Cytują klasyka: „W d… bede grał w gre”. Na obietnicach się skończyło. Chłopaki i dziewczyny nie wyrobili się z MAUI na tą wersję, chociaż można już testować PREVIEW. Jest szansa, że w wersji produkcyjnej pojawi się w przeciągu 6 miesięcy.


To na razie tyle z mojego pierwszego spojrzenia. Mimo to, że VS2022 jest jeszcze gorący jak bułki z piekarni, to jednak warto go zainstalować i używać. Jestem naprawdę pozytywnie zaskoczony. Wersję Community możesz pobrać stąd: https://visualstudio.microsoft.com/pl/thank-you-downloading-visual-studio/?sku=Community&rel=17

A Ty zainstalowałeś już VS2022? Jakie są Twoje spostrzeżenia? Podziel się w komentarzu.

Podziel się artykułem na:
Gdy okienko jest za małe, czyli WPF i problem z monitorem 4K

Gdy okienko jest za małe, czyli WPF i problem z monitorem 4K

Super! Dostałeś nowy monitor 4k! Nic tylko szaleć. Odpalasz swój program napisany w WPF i… gówno widzisz. Wszystko jest za małe. Jak to się dzieje? Przecież obiecali, że WPF ogarnia DPI, czy coś tam i nie trzeba już nic robić…

No tak. Niby ogarnia, ale nie ogarnia zmiany DPI przy kilku monitorach. To automatycznie robią aplikacje pisane w UWP. Natomiast w WPF trzeba zrobić mały, prosty myk. Ale spokojnie, nie musisz przepisywać aplikacji, stosować jakiś ViewBoxów, czy skomplikowanych obliczeń. Wszystko zostanie załatwione w pliku manifestu.

Windows 10 od wersji 1703 używa czegoś takiego jak Per-Monitor v2 awarness mode. Po krótce chodzi o to, że potrafi rozpoznać, kiedy okno aplikacji jest przesuwane na monitor z inną rozdzielczością. Teraz musimy poinformować naszą aplikację WPF, że też to potrafi:

Rozwiązanie

1. Utwórz plik manifestu (jeśli używasz domyślnego) lub otwórz jeśli już go masz.

Aby utworzyć plik manifestu:

  • kliknij prawym klawiszem myszy na projekt
  • wybierz Add -> New Item
  • odnajdź plik manifestu (wpisz w okienko do szukania: manifest)

2. Jeśli utworzyłeś nowy plik manifestu, to prawdopodobnie już wszystko masz. Wystarczy znaleźć fragment <application xmlns="urn:schemas-microsoft-com:asm.v3"> i go odkomentować.

3. Powinieneś w pliku manifestu mieć taki fragment:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
  </windowsSettings>
</application>

I tyle. Upewnij się, że Twoja aplikacja używa tego pliku. Aby to zrobić:

  • kliknij prawym klawiszem myszy na projekt
  • wejdź w ustawienia (Properties)
  • na karcie Application upewnij sie, że w ComboBox Manifest masz podany swój plik manifestu.

Uruchom apkę… I to tyle.

Podziel się artykułem na:
Różne typy projektów w VisualStudio 2019

Różne typy projektów w VisualStudio 2019

Po pewnych zmianach w Visual Studio 2019, tworzenie projektów może być nieco niezrozumiałe zwłaszcza dla młodszych programistów. Ten artykuł wyjaśnia po kolei typy projektów w VisualStudio i jest kierowany głównie do początkujących.

Jaki utworzyć projekt

Stworzyłem specjalnie na potrzeby tego artykułu prosty i nieidealny algorytm do wyboru typu projektu. Możesz go pobrać stąd

Algorytm wyboru odpowiedniego typu projektu

Co możemy utworzyć

Visual Studio daje nam właściwie nieograniczone możliwości. Pomaga utworzyć projekt na dowolną platformę w konkretnym języku i w wybranej technologii (gdzie można). Tak wygląda okienko tworzenia nowego projektu:

Okienko tworzenia nowego projektu w Visual Studio
Tworzenie nowego projektu

Okienko jest podzielone na dwie główne grupy. Z lewej strony znajduje się lista ostatnich używanych typów projektów. Po prostu możesz kliknąć na to, co już ostatnio tworzyłeś i nie musisz szukać w liście po prawej stronie.

Z prawej strony masz z kolei grupę podzieloną na dwa elementy. Na górze filtr, na dole listę dostępnych typów projektów. One mogą być różne w zależności od tego, jak zainstalowałeś Visual Studio (typy też można dodawać i usuwać z poziomu instalatora: Visual Studio Installer, który znajduje się na Twoim komputerze)

Jeśli teraz zaczniesz wpisywać w filtrze na górze nazwę typu projektu, który chcesz utworzyć, lista automatycznie zacznie się zmieniać. Ja przykładowo wpisałem Console i zobacz, jak wygląda moja lista na obrazku wyżej. Tych projektów jest dużo więcej. Teraz postaram się część z nich omówić:

Add-In

To jest po prostu rozszerzenie (plugin) do Visual Studio. Tak, można pisać własne pluginy. Będę o tym pisał w niedalekiej przyszłości. Tak naprawdę całe Visual Studio składa się z pluginów. Jak widzisz są to projekty VSIX.

VSIX Project

To projekt rozszerzenia VisualStudio z dodanymi już pewnymi plikami i kodami. Takich projektów jest kilka w zależności od języka, w którym piszesz (C#, VisualBasic)

WIdok projektu Add-In

Empty VSIX Project

jest to zupełnie pusty projekt rozszerzenia VisualStudio. Od tego powyżej różni się brakiem kodów i domyślnych plików. Wszystko piszesz od zera. Ma to swoje plusy i minusy.

Widok pustego projektu Add-In

Empty VSIX Project (Community)

to samo, co wyżej z tą różnicą, że zawiera referencje do biblioteki Community.VisualStudio.Toolkit, co ułatwia pisanie rozszerzeń

VSIX Project w/Command (Community)

ten template zawiera to co VSIXProject, dodatkowo posiada referencje do Community.VisualStudio.Toolkit i dodatkowo posiada napisaną już komendę. Ten suffiks w/Command czytaj jako „with command”

Widok projektu Add-In Community

VSIX Project w/Tool Window (Community)

Uuuu, to jest dopiero mocarz. Zawiera wszystko to, co VSIX Project w/Command (Community), ale dodatkowo własne okno narzędziowe (Tool window)

Widok projektu Add-In z okienkiem

Który projekt wybrać do tworzenia rozszerzenia? To oczywiście zależy. Najbardziej obszernym zdecydowanie jest VSIX Project w/Tool Window (Community) i może się wydawać najlepszym. Tam, gdzie używasz okien i komend może to być szybki start. Oczywiście jeśli wcześniej nie tworzyłeś żadnych rozszerzeń, polecam zaczynać od najmniejszego projektu Empty VSIX Project. Nie przytłoczy Cię duża ilość plików na początek i będziesz mógł rozwijać rozszerzenie w swoim tempie, ucząc się powoli nowych rzeczy.

Console

Czym są aplikacje konsolowe?

Aplikacje konsolowe tworzone są na komputery. Często są to jakieś narzędzia dostępne z wiersza poleceń lub proste programy testowe, gdzie szybko chcemy sprawdzić jakieś funkcjonalności.

Konsola

Ale aplikacje konsolowe potrafią być często naprawdę dużymi, poważnymi narzędziami. Czasami posiadają nakładki graficzne, dzięki którym łatwiej je obsługiwać. Zdarzają się też proste gry tekstowe lub z grafiką w postaci ASCII Art.

Typy aplikacji konsolowych

  • Console Application (dostępna w różnych językach: C#, F#, VisualBasic…) – podstawowa aplikacja konsolowa na komputery. Podczas jej tworzenia zostaniesz zapytany o wersję .NetCore, której używać
Wybór framework

Domyślnie w tej wersji Visual Studio aplikacje konsolowe są tworzone w .NetCore. W tym miejscu możesz wybrać wersję, której chcesz używać.

Jest to właściwie najmniejszy template. Domyślnie posiada tylko jeden plik Program.cs z małym fragmentem kodu.

Chociaż długo sam nie potrafiłem tego pojąć, to jednak aplikacje konsolowe są tym typem, od którego powinno zaczynać się naukę programowania. Po prostu jest wtedy dużo prościej pojąć pewne rzeczy.

Blank Node.js console application

są dwie wersje zależne od języka. JavaScript lub TypeScript. Jeśli nie wiesz, czym jest TypeScript, to po prostu JavaScript z typami. Sam TypeScript jest kompilowany później do JavaScript. Generalnie to jest najmniejszy template do tworzenia aplikacji w Node.js

Console App (.Net Framework)

to jest aplikacja konsolowa, zupełnie taka jak domyślna Console Application. Też dostępna w kilku językach. Różnica jest taka, że używając tego templatu, będziesz miał do dyspozycji cały .Net Framework. Ale uwaga, ten typ projektu tworzy aplikacje jedynie dla Windowsa.

Widok projektu konsolowego

Standalone code analysis tool

to służy do tworzenia analizatorów kodu. Jakiś czas temu w VisualStudio pojawiły się takie analizatory kodu, które za pomocą Roslyn potrafią podpowiedzieć Ci kilka rzeczy. Np., że powinieneś dany fragment kodu wywołać w wątku głównym. Albo, że możesz jakiś kod napisać czyściej. Dzięki temu VisualStudio potrafi też automatycznie dodać odpowiednie namespacey do pliku cs. Oczywiście nic nie stoi na przeszkodzie, żeby napisać własne analizatory. Do tego służy ten template.

Jak widzisz mamy tutaj właściwie 4 różne typy aplikacji do wyboru – Kosnola dla Windows, konsola niezależna od systemu (.NetCore)*, konsola w Node.js no i analizator kodu.

Pisząc „konsola niezależna od systemu” mam na myśli, że kiedyś tak może być. Na dzień dzisiejszy aplikacje konsolowe i okienkowe są tworzone tylko pod Windows. Ale w przyszłości może się to zmienić. Wtedy dużo prościej będzie przejść z aplikacji pisanej w .NetCore (lub będzie to w standardzie)

Desktop

To jest to, co lubię najbardziej. Stare, dobre aplikacje na komputery :). Tutaj tworzymy głównie aplikacje okienkowe i wszystko co z nimi powiązane (biblioteki, kontrolki, serwisy), ale możemy też znaleźć templaty do testów jednostkowych.

Opiszę pokrótce niektóre typy:

Windows Forms

  • Windows Forms App – tworzymy aplikację okienkową w technologii WindowsForms. Jedynie dla Windows. Używamy wybranej wersji .NetCore. Dostępne dla C# i VisualBasic
  • Windows Forms Class Library – biblioteka dll, której możemy używać w aplikacjach Windows Forms App. Jedynie dla Windows.
  • Windows Forms Control Library – biblioteka, w której możemy tworzyć dodatkowe kontrolki i używać ich w Windows Forms App. Tutaj też piszemy tylko dla Windows i w .NetCore.
  • Windows Forms * (.NET Framework) – te kilka pozycji jest analogiczne do tych powyżej. Z tą jedynie różnicą, że mamy do dyspozycji pełny .NET Framework

UWAGA! Pamiętaj o tym, że nie możesz mieszać ze sobą technologii .NetCore i .NET Framerowk. To znaczy, że jeśli tworzysz aplikację w .NetCore, to nie będziesz mógł użyć w niej .NET Framework.

WPF (Windows Presentation Foundation)

  • WPF Application – nowsza technologia niż Windows Forms. Używamy kodu XAML do projektowania okienek. Używamy wybranej wersji .NetCore. Dostępne jedynie dla Windows.
  • WPF Class Library – analogicznie jak w Windows Forms. Po prostu dllka, której możemy używać w WPF Application. Używamy wybranej wersji .NetCore i piszemy tylko dla Windows
  • WPF Custom Control Library – analogicznie jak w Windows Forms Control Library. Tworzymy kontrolki dla aplikacji WPF. Używamy wybranej wersji .NetCore i piszemy tylko dla Windows
  • WPF UserControl Library – tutaj mały haczyk. Możemy tworzyć „kontrolki” dziedziczące po UserControl i używać ich w aplikacji WPF. Nie ma to odpowiednika w WindowsForms, ponieważ WPF wymaga nieco innego podejścia. Używamy wybranej wersji .NetCore i piszemy w Windows.
  • WPF Application (.NET Framework) – to samo, co wyżej z tą różnicą, że używasz pełnej wersji .NET Framerowk

UWAGA! Pamiętaj o tym, że nie możesz mieszać ze sobą technologii .NetCore i .NET Framerowk. To znaczy, że jeśli tworzysz aplikację w .NetCore, to nie będziesz mógł użyć w niej .NET Framework.

Universal Windows

To są aplikacje, które mogą działać na wszystkich platformach z Windowsem. Na komputerach, telefonach (z Windowsem), XBox… Generalnie wszędzie tam, gdzie jest zainstalowany Windows. Co ciekawe, sam możesz tworzyć swoje urządzenia z odpowiednim chipem i tworzyć aplikacje, które będą na nim pracowały.

Te aplikacje też wykorzystują XAML do tworzenia okienek, ale robi się je zupełnie inaczej niż aplikacje w WPF. Mają zupełnie inny cykl życia i inne kontrolki.

Windows Service

To są usługi, które pracują w systemie. Po prostu takie aplikacje bez okienek, które pracują cały czas w tle.

Mobile

W tej kategorii znajdziemy templaty do tworzenia aplikacji mobilnych. Głównie w technologii Xamarin. Nie będę się tu za bardzo wysilał, bo też nie ma nad czym. Opiszę tylko w kilku słowach, czym jest Xamarin.

Xamarin

Wszystkie aplikacje oznaczone jako Xamarin, są pisane w technologii Xamarin. No tak, a masło jest z masła. Generalnie Xamarin to taka technologia, która próbuje połączyć ze sobą różne platformy. Android, iOS, Universal Windows i inne. Celem, jaki temu przyświeca jest to, żeby jak największa część kodu była współdzielona pomiędzy te wszystkie aplikacje. Zarówno część wizualna (Xamarin.Forms) jak i cała logika.

Mimo, że technologia ma już kilka lat, to jednak cały czas (maj 2021) są z nią jakieś problemy i czasami pewne rzeczy trzeba napisać inaczej niż by się chciało. Ale cały czas jest rozwijana i ulepszana. I faktycznie z roku na rok wygląda to coraz lepiej.

Co do reszty templatów (np. Photo Editing Extension) nie będę się rozpisywał, bo nie miałem z nimi do czynienia. Można się domyślić, że jeśli chcesz napisać aplikację na telewizor, użyjesz odpowiedniego templatu z oznaczeniem tvOS (chyba, że piszesz na Androida). Jeśli interesuje Cię coś konkretnego z tej listy poza Xamarin, odsyłam do google 🙂

Other

U siebie mam tylko jeden typ – Blank Solution. I mogłoby paść pytanie – po co komu pusta solucja z samym tylko plikiem sln? Trochę jest to przeszłość, a czasami tak po prostu zaczyna się większe projekty. Pozwala Ci to od początku panować całkowicie nad strukturą katalogów i dodatkowych plików, których chcesz używać.

Web

No i doszliśmy do momentu, w którym mamy aplikacje typowo Webowe. Czyli to, co dzisiaj zdecydowanie jest na topie. Visual Studio umożliwia nam tu utworzenie kilku typów:

ASP.NET Core Empty

To jest pusta aplikacja webowa. Możesz z niej zrobić WebAPI, stronę internetową lub co tylko dusza zapragnie w webie. Podczas tworzenia zostaniesz zapytany o pewne ustawienia:

Wybór framework
  • TargetFramework – podajesz tutaj, jakiego frameworka chcesz używać. Zazwyczaj wybierzesz .NetCore 3.1 lub .NET 5
  • Configure for HTTPS – dzisiaj świat na wysokim miejscu stawia bezpieczeństwo. Również w sieci. Jeśli zaznaczysz tę opcję, projekt będzie skonfigurowany do pracy z protokołem HTTPS. Podczas pierwszego debugowania takiego projektu, Visual Studio utworzy i zainstaluje dla Ciebie specjalny certyfikat (Self Signed Certificate), a przeglądarki podczas pierwszego uruchomienia ostrzegą Cię, że ten certyfikat jest niebezpieczny i nie pochodzi z zaufanego źródła. Nie jest to w tym momencie istotne. Ważne, że gdy opublikujesz taką aplikację w sieci, musisz mieć na serwerze poprawny certyfikat. Dzisiaj można go otrzymać za darmo od Let’s Encrypt. Serwer, na którym mam swoje aplikacje – HostedWindows umożliwia utworzenie takiego certyfikatu i automatyczne przedłużenie go, za pomocą jednego kliknięcia.
  • Enable Docker – jeśli nie wiesz, czym jest docker, to moje wyjaśnienie nic Ci nie powie. Jeśli wiesz, to wiesz do czego służy ta opcja 🙂

A czysta aplikacja wygląda tak:

Widok projektu webowego

ASP.NET Core WebAPI

To jest template, który wykorzystasz konkretnie do utworzenia restowego WebAPI. Jeśli nie wiesz, czym jest restowe WebAPI, to bardzo krótko mówiąc…

Wyobraź sobie, że masz aplikację, w której chcesz wyświetlić wszystkich swoich znajomych z Facebooka. Facebook wystawia takie WebAPI (nie jest to restowe, ale dla przykładu załóżmy, że jest) i teraz możesz się z nim skomunikować i zapytać go o listę swoich znajomych, wywołując taki adres: https://api.facebook.com/friends

Ten adres jest tzw. „endpointem”. Podany przeze mnie endpoint nie istnieje w rzeczywistości, został wymyślony na potrzeby artykułu. Ale tak to mniej więcej działa – aplikacja wywołuje odpowiedni adres (endpoint), a serwer, jeśli Twoje uprawnienia na to pozwolą, odpowiada w jakiś ustalony sposób. Najczęściej odpowiedź jest w formie JSON, rzadziej XML.

Podczas tworzenia projektu tego typu, zostaniesz poproszony o dodatkowe informacje:

Wybór framework

Większość jest analogicznie jak wyżej z jedną małą różnicą.

  • Authentication Type – w projekcie WebAPI możesz i powinieneś w jakiś sposób autentykować i autoryzować swoich użytkowników. Ten artykuł zdecydowanie nie jest miejscem na wyjaśnienia co, jak i dlaczego, bo zagadnienie jest dość obszerne. Wkrótce o tym napiszę. Jeśli nie wiesz o co chodzi, to zostaw na None.

Projekt WebAPI nieco różni się od pustego:

Widok projektu WebAPI

Jak widzisz doszedł folder Controllers, zawierający kontrolery i kilka innych plików. Kod też jest inny. Zatem, jeśli chcesz stworzyć WebAPI, to zdecydowanie zacznij od tego projektu. Własne proste WebAPI dzięki temu można stworzyć w 10 minut (co dzisiaj udowodniłem komuś :)).

ASP.NET Core Web App

To jest typowa strona internetowa. Frontend tworzy się w RazorPages. A całość po utworzeniu wygląda tak:

Widok projektu RazorPages

ASP.NET Core App (Model-View-Controller)

To jest już aplikacja webowa, używająca wzorca MVC. Front tworzy się w RazorViews. Generalnie jest to bardzo podobne do RazorPages z pewnymi niuansami. Same dwa templaty (ten i poprzedni) są do siebie bardzo podobne i czasem jest ciężko stwierdzić, który będzie lepszy.

Generalnie zasada jest taka, że do prostych stron używamy raczej Razor Pages (ASP.NET Core App tego pierwszego), natomiast do bardziej skomplikowanych używamy MVC. Dodatkowo ten projekt może zawierać WebAPI. Ale osobiście radziłbym nie mieszać.

Utworzony pusty projekt wygląda tak:

Widok projektu Razor MVC

ASP.NET Web Application (.NET Framework)

To jest stary typ aplikacji webowych, który został zastąpiony .NET Core. Niemniej jednak mnóstwo aplikacji jest w tym utrzymywanych i rozwijanych. Odradzam używanie tego templatu do nowych programów.


No to tyle jeśli chodzi o podstawowe typy projektów. Jest ich jeszcze sporo, dodatkowe przychodzą z innymi pluginami, ale ich nazwy raczej same się opisują.

Jeśli znalazłeś w tekście błąd lub masz problem, podziel się w komentarzu

Podziel się artykułem na: