Sytuacja kobiet w IT w 2024 roku
17.09.20208 min
Hubert Morawski

Hubert MorawskiC# DeveloperCode Hydra

Tworzenie biblioteki do Web API w .NET

Sprawdź, jak stworzyć działającą bibliotekę Web API w .NET i wrzucić ją na GitHuba oraz NuGet.

Tworzenie biblioteki do Web API w .NET

Dzięki stworzeniu swojej własnej biblioteki można nie tylko wesprzeć społeczność open source, ale również nauczyć się wielu przydatnych rzeczy. Co ważne, gdy już projekt będzie gotowy jest duża szansa, że znajdą się ludzie chętni do pomocy w rozwoju!

Znalezienie API

Zanim zaczniemy kodować musimy najpierw znaleźć API, do którego chcielibyśmy napisać bibliotekę. Może to być jakieś narzędzie, z którego korzystamy, żeby biblioteka również służyła nam.  

A co jeśli nie mamy takiego API? Mogę polecić kilka dobrze udokumentowanych API

  • Github API- świetne API, które pozwala na zrobienie dosłownie wszystkiego na Github
  • PokeAPI - API które zwraca informacje o Pokemonach. I Ty możesz zrobić swój Pokedex!
  • MTG API- API z informacjami o kartach popularnej gry Magic The Gathering


Jednak te API mają już swoje biblioteki w C#. Zamiast tego proponuje jedno z tych zabawnych API, które jeszcze czekają na swoje biblioteki:

  • Cat facts API- ciekawe API, które zwraca fakty o kotach.
  • Jokes API - API, które zwraca żarty. Nigdy nie wiadomo na co się trafi.
  • Potter API- Harry Potter API zawierające informacje o postaciach, domach i zaklęciach ze świata Harry’ego Potter’a.


Jeśli ciągle brakuje inspiracji, to polecam zerknąć na jeszcze więcej publicznych API.

Tworzenie projektu na GitHub

Zróbmy najpierw repozytorium na GitHub dla naszego projektu. Wystarczy, że wejdziemy na stronę GitHuba (oczywiście musimy mieć konto), klikniemy + i New repository

Otworzy się przed nami formularz, w którym należy uzupełnić pola::

  1. Repository name - tu powinna być nazwa naszego projektu.
    W C# biblioteki najczęściej mają nazwy z końcówką “.Net” np. Nazwa.Net lub coś z dodatkiem “Sharp” np. NazwaSharp.
  2. (Opcjonalne) Krótki opis projektu. Zachęcam do napisania kilku słów, dzięki czemu nasz projekt będzie można łatwiej wyszukać.
  3. Typ repozytorium to oczywiście Public
  4. (Opcjonalne) Add a README file - dzięki temu GitHub sam wygeneruje nam plik z opisem projektu. Przydatna opcja. Polecam zaznaczyć.
  5. (Opcjonalne) Add .gitignore - automatycznie generuje nam plik .gitignore. Zalecam wybrać opcje “Visual Studio”, która doda domyślne katalogi z C# i Visual Studio.
  6. License - wybór licencji. Bardzo ważne pole. Jeśli projekt nie będzie miał licencji to nie będzie można z niego swobodnie korzystać. Najpopularniejsze licencje open source to MIT i Apache 2.0.


Wystarczy kliknąć Create repository i gotowe!

Czas sklonować nasze repozytorium przy użyciu ulubionego klienta gita. Link można znaleźć na stronie projektu w tym miejscu.

Lub użyć konsoli

git clone https://github.com/Morasiu/CatFacts.Net.git


Jeśli ciągle masz problem z tworzeniem lub klonowaniem projektu zerknij na pomoc GitHub.

Projekt biblioteki .Net

Teraz stwórzmy projekt naszej biblioteki. Najłatwiej użyć do tego Visual Studio i wybrać “Biblioteka klas (.NET Standard)”:

Ewentualnie można to zrobić za pomocą konsoli:

dotnet new sln -n CatFacts.Net
dotnet new classlib -n CatFacts.Net


Dzięki temu, że projekt jest przeznaczony na .Net Standard będzie można go używać w każdym innym projekcie. Niezależnie czy to .Net Core, .Net Framework czy Xamarin itp.

Następnie musimy wybrać bibliotekę do łączenia się z API. Zajmie się ona niskopoziomowymi rzeczami i znacznie przyśpieszy proces tworzenia. W C# mamy kilka wiodących narzędzi do tego:

  • Flurl-  przyjemna biblioteka, która pozwala na pisanie zapytań w stylu fluent
  • HttpClient- domyślna narzędzie od Microsoftu, wbudowane w .Net
  • RestSharp- prosta i łatwa w użyciu biblioteka


W tym przykładzie użyjemy RestSharp, ale zachęcam do wybrania narzędzia, które najbardziej Wam pasuje.

Aby dodać RestSharp do projektu możemy znowu posłużyć się Visual Studio:

  • Klikamy prawym przyciskiem myszy na nazwę projektu w Solution Explorer, a następnie Manage NuGet Packages…



  • Następnie wyszukujemy RestSharp i dodajemy do projektu

Alternatywnie możemy użyć konsoli do tego:

dotnet add package RestSharp


Projekt gotowy, czas rozpocząć tworzenie!

Kodowanie

Na początku sprawdźmy jakie endpointy musimy zrobić, żeby nasza biblioteka miała sens. Skorzystamy z przykładu Cat facts API.

Jak widać są dwie listy endpointów, /facts i /users


Nie trzeba wspierać wszystkich endpointów. Wystarczy, że na początek będziemy wspierać  tylko te główne.


Zacznijmy od napisania naszej głównej klasy CatFactsClient.

using RestSharp;

namespace CatFacts.Net {
	public class CatFactsClient {
		private RestClient _restClient;

		public CatFactsClient() {
			_restClient = new RestClient("https://cat-fact.herokuapp.com");
		}
	}
}


Jak widać jest to dość prosta klasa. Stworzyliśmy podstawę do naszego klient. W środku jest nasz wewnętrzny REST klient którego będziemy używać do wysyłania zapytań do API.

Jeśli API, którego używamy ma wiele endpointów i nasz klient robi się rozdęty możemy podzielić go na tzw. Partial classes.

W końcu czas na napisanie pierwszej metody do API, które wybraliśmy. Głównym wykorzystaniem Cats Facts API jest uzyskiwanie losowych faktów o kotach, więc zacznijmy od napisania metody do endpointu GET /facts/random. Ten endpoint zwraca listę modeli Facts, więc musimy zrobić odpowiednik modelu w klasie C#. W dokumentacji widzimy, że model Fact wygląda tak:

Jego odpowiednik w klasie C# powinien wyglądać tak:

namespace CatFacts.Net.Models {
	public class Fact {
		[JsonProperty("_id")]
		public string Id { get; set; }

		[JsonProperty("__v")]
		public int? V { get; set; }

		public string User { get; set; }

		public string Text { get; set; }

		public DateTime? UpdatedAt { get; set; }

		public DateTime? SendDate { get; set; }

		public bool? Deleted { get; set; }

		public Source? Source { get; set; }

		public bool? Used { get; set; }

		public string Type { get; set; }
	}

	public enum Source {
		User,
		Api
	}
}


Możemy też skopiować opis każdego pola z dokumentacji i dodać je w ten sposób w komentarzach XML.

/// <summary>
/// Unique ID for the Fact
/// </summary>
[JsonProperty("_id")]
public string Id { get; set; }


Dzięki temu nikt nie będzie się zastanawiał czym jest każde pole.

W końcu czas napisać metodę do klasy CatFactsClient. Jak widzimy endpoint zwraca listę faktów, więc również to powinna zwracać nasza metoda.

public List<Fact> GetRandomFacts() {

}


Wysłanie zapytania przy użyciu RestSharp jest bardzo proste. Wystarczy kilka linijek.

public List<Fact> GetRandomFacts() {
	var request = new RestRequest("/facts/random");
	var facts = _restClient.Get<List<Fact>>(request);
	return facts.Data;
}


Dobrą praktyką w C# przy robienie metod, które łączą się z zewnętrznymi usługami (np. Baza danych, API itp.) jako asynchroniczne. Dzięki czemu nie będą blokować wątków UI w aplikacjach graficznych np. WPF. Szybkie przerobienie na metody na asynchroniczną wygląda tak:

public Task<List<Fact>> GetRandomFactsAsync() {
	var request = new RestRequest("/facts/random");
	var facts = _restClient.GetAsync<List<Fact>>(request);
	return facts;
}


Jak widać nie zmieniło się dużo.

  • Teraz metoda zwraca Task<>
  • Zgodnie z konwencją C# na końcu metody dodano Async
  • Zmieniono _restClient.Get na _restClient.GetAsync


I nasza implementacja w wersji podstawowej jest gotowa. Ale w dokumentacji widzimy, że można jeszcze dodać query parameters

Nowa wersja ze wsparciem parametrów wygląda tak:

public Task<List<Fact>> GetRandomFactsAsync(int amount = 1, params string[] animalTypes) {
	var request = new RestRequest("/facts/random");

	request.AddQueryParameter("amount", amount.ToString());
	request.AddQueryParameter("animal_type", string.Join(",", animalTypes));

	var facts = _restClient.GetAsync<List<Fact>>(request);
	return facts;
}


I gotowe. Tylko skąd wiemy, że to w ogóle działa? Najlepiej sprawdzić to poprzez napisanie testów.

Testy

Każdy dobry projekt powinien mieć testy. W dzisiejszych czasach mamy do wyboru wiele świetnych frameworków do testów np. xUnit, NUnit. Dla przykłady wybierzmy tutaj NUnit.

Zacznijmy od stworzenia nowego projektu testowego. Kolejny raz możemy użyć do tego Visual Studio. Najpierw wybieramy Add -> New Project...

I następnie wybieramy NUnit Test Project

Nazwijmy go CatFacts.Net.Tests.

Jeszcze tylko dodajmy referencje do naszego głównego projektu. Klikamy na Add -> Project References.

Zaznaczamy checkbox przy CatFacts.Net, klikamy Ok i gotowe!

Gdy zerkniemy teraz do naszego projektu testowego naszym oczom ukaże się czysta klasa testowa. Po drobnych zmianach i usunięciu niepotrzebnych rzeczy powinniśmy mieć taką czystą klasę:

using NUnit.Framework;

namespace CatFacts.Net.Tests {
	public class CatFactsClientTests {

		[Test]
		public void Test1() {
			Assert.Pass();
		}
	}
}


Nazwijmy nasz test nieco lepiej niż Test1. Jest wiele konwencji nazywania testów. Osobiście preferuję:

NazwaMetody_WarunkiLubDane_ShouldCoPowinnaZrobić

Więc zgodnie z tą konwencją test powinien nazywać się:

[Test]
public void GetRandomFactsAsync_WithoutQueryParameters_ShouldReturnFactsList() {
	
}


Nie należy się przejmować długimi nazwami. Lepiej, żeby nazwa była długa, niż żeby zawierała za mało informacji.

W końcu możemy napisać nasz test. W najprostszej formie będzie wyglądać tak:

[Test]
public async Task GetRandomFactsAsync_WithoutQueryParameters_ShouldReturnFactsList() {
	// Arrange
	var client = new CatFactsClient();
	// Act
	var facts = await client.GetRandomFactsAsync();
	// Assert
	Assert.NotNull(facts);
}


Znaczące zmiany tutaj to:

  • Zmieniono metodę na async
  • Dodano komentarze zgodnie z zasadą Arrange, Act, Assert. Dla czystości testów.


I nasz pierwszy uproszczony test jest gotowy!

Udostępnianie

W końcu nadszedł czas udostępnienia naszego pakietu. Zacznijmy od zmiany wersji we Właściwościach projektu. Można je znaleźć tutaj.

Klikamy prawy przyciskiem myszy na projekt, a następnie na Properties. Ukaże nam się nowe okno. Należy tam przejść do Package.

Następnie należy tam zmienić kilka rzeczy

  • Zaznaczyć checkbox Generate NuGet package on build
  • Zmienić wersję na 0.1.0 (zgodnie z Semantic Versioning)
  • Dodać krótki opis. Najlepiej przekopiować z Githuba
  • Dodać link do repozytorium


Oczywiście na końcu zapisać zmiany!

Projekt gotowy. Czas na build. Najpierw zmieńmy konfiguracje z Debug na Release

Teraz czas zrobić paczkę NuGet. Wystarczy w menu kontekstowym (po kliknięciu prawym przyciskiem myszy na projekt) wybrać opcje Pack.

Naszą paczkę znajdziemy w KatalogProjektu/bin/Release. Powinna być nazwana NazwaProjektu.0.1.0.nupkg. W moim przypadku to CatFacts.Net.0.1.0.nupkg.

Tylko co teraz zrobić z taką paczką?

  1. Wchodzimy na NuGet.org
  2. Logujemy się lub zakładamy konto.
  3. Następnie w naszym profilu wybieramy opcję Upload Package.



  4. Dodajemy naszą paczkę tutaj


    Opcjonalnie możemy dodać tutaj link do naszego README z Githuba. 


    README musi być w formacie raw, żeby to zadziałało.

  5. Klikamy Submit i gotowe! Nasza pierwsza paczka jest ogólnie dostępna.


Udało nam się stworzyć działającą bibliotekę i wrzucić ją GitHub oraz NuGet. Co teraz? Zachęcam do pochwalenia się nią na różnych platformach. Np. 

  • Reddit (r/csharp, r/dotnet)
  • Grupy programistyczne
  • Znajomi programiści


Dzięki temu ktoś skorzysta z naszej paczki, a może nawet pomoże ją rozwijać. Możemy też poprosić innych programistów o swoje opinie o naszym kodzie co pozwoli nam zostać jeszcze lepszymi programistami!

PS: Cały przykładowy projekt CatFacts.Net można zobaczyć tutaj. A jeśli chcesz zobaczyć nieco bardziej rozbudowany przykład to zapraszam do zerknięcia do mojej autorskiej biblioteki tutaj.

<p>Loading...</p>