Wspólne modele dla dotnet i typescript

Trawa za płotem bardziej zielona

W Blazor’ze bardzo podoba mi się to, że brane są modele z dotnet (czy to api, czy to dowolna warstwa) i że każda zmiana na “backendzie” za darmo i od razu dostępna na “froncie”. Typescript ma fajne to, że można sobie silnie typować obiekty i że ten javascript jest takie ciut pewniejszy. Angular dla mnie mocno przypomina MVC więc z niego korzystam – ale! Jestem dobry w narzekanie; ale nie ma tego co ma blazor – a ja bym chciał. Bo takie przepisywanie modeli z dotnet na typescript to jest nudne, coś zmienisz, albo machniesz literówkę i trzeba szukać. Lubię też się wyręczać robotą kogoś innego 😉

google is your friend

Także poszukałem jak to ogarnąć. Co? No to, jak z klas w dotnet generować  klasy / kod do typescript, który można potem wykorzystać w projekcie na froncie.

Kto to może zrobić za mnie

Ja znalazłem takie narzędzia, które na dłużej przykuły moją uwagę:

  1. https://github.com/reinforced/Reinforced.Typings
  2. https://github.com/jburzynski/TypeGen

Wybrałem opcje numer 1, trochę świeższa wersja na githubie – i tym doświadczeniem chce się podzielić

dotnet 👉 typescript

Export z dotnet można zrobić przez atrybuty (ja nie chce, ponieważ nie chce dołączać zbędnych nugetów do proda ⭐), można przez fluenta – i tak właśnie zrobiłem to u siebie:

Export znajduje się w osobnym projekcie, który referuje do klas które chce eksportować, ale nikt nie referuje do niego:

Mam takiego enuma u siebie w kodzie .cs:

I innego podobnego, ale nie ważne.  Następnie w osobnym projekcie mam taką konfigurację exportu:

Export 2x enum oraz model kanału.

To powoduje że po zbudowaniu projektu będę mieć następujące pliki w projekcie frontu:


Są tam enumy, model widoku znajduje się w innym namespace, a więc inny folder – tak sobie wymyśliłem

Tak; ITAN jest monorepo – to bardzo mi ułatwia życie.

Następnie ze swojego frontu zaciągam to tak:

import {UpdatedNews} from “../../../server/Itan/Common/UpdatedNews”;

await this.settingService.squashNewsUpdates(SquashUpdate.Squash);

🎂 Gotowe

I jest! Teraz przy każdej zmianie w .net mogę spokojnie wykorzystywać te same modele czy enumy na froncie. Po pierwsze oszczędza mi to czas na tworzenie obiektów na froncie. Oszczędza czas na szukaniu literówek, które tak bardzo kocham, czy też rozwiązuje problem współdzielenia kodu – tyle wygrać.

💡 Inspiracja

Przykład jest oparty o produkcyjna już aplikację ITAN (isthereanynews.com), nad którą pracuje w czasie wolnym. ITAN to raczkujący czytnik RSSów z planami i ambicjami. Możesz śledzić tagi #isthereanynews na tym blogu, Twitterze czy odwiedzić stronę.

🤔 Uwaga

⭐ Tak sobie myślę, jest jeden minus do podejścia bez atrybutów. Użycie tych modeli jest ukryte i zmiana / problem pojawi się dopiero podczas kompilacji / uruchomienia. Póki co jednak jestem zdania, że nadal wolę to mieć odseparowane.

2 thoughts on “Wspólne modele dla dotnet i typescript

  1. Dzięki za materiał, chyba wszystkie full-stacki się z tym problemem stykają :-). To podejście jest fajne i na pewno często wystarcza. Jest proste w implementacji, w szczególności przy monorepo.

    Alternatywnym rozwiązaniem które teraz stosuję jest najpierw wygenerowanie swaggera dla swojego serwisu (Swashbuckle) a następnie z wyjściowego schematu automatycznie wygenerowanie całego klienta (@openapitools/openapi-generator-cli).
    Ma to szereg zalet, między innymi:
    a) możemy wygenerować całego klienta (serwisy, autoryzacja etc) a nie tylko modele
    b) ze wspólnego modelu swaggera możemy już potem łatwo generować kolejne klienty dla innych technologii/języków programowania, użyć go w serwisach typi API management itd.
    c) Swashbuckle sam wykrywa które modele/enumy są faktycznie używane w API i tylko je eksportuje

    Wadą jest na pewno większe skomplikowanie procesu generowania, które być może nie ma uzasadnienia dla mniejszych projektów.

    1. Sprawdzę, bo w większym projekcie gdzie klikam, chcemy to automatyzować i skleić jakoś w procesie CI/CD. Bez klienta z tylko modele, które latają pomiędzy frontem a API

Leave a Reply

Your email address will not be published. Required fields are marked *

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