Tłumaczenie aplikacji mobilnych – XAMARIN

Tłumaczenie aplikacji mobilnych – XAMARIN

Wstęp

To jest kolejny artykuł z serii o globalizacji i lokalizacji. Jeśli nie czytałeś poprzednich, koniecznie to nadrób. W tym artykule opisuję TYLKO jak ładować tłumaczenia w aplikacjach mobilnych tworzonych w XAMARIN. Poprzedni artykuł – Tłumaczenie aplikacji cz. 3 – jak to ogarnąć? – daje całą podstawę.

Piszemy MarkupExtension

W XAMARINie, jak i w WPF, też mamy do czynienia z językiem XAML. Wersja dla Xamarina może i nie jest tak rozbudowana, jednak pozwala na dużo. I tutaj też posłużymy się MarkupExtension. Jeśli nie wiesz co to, w skrócie to jest interfejs (w WPF to jest klasa), który pozwala Ci na tworzenie własnych tagów XAML. Wystarczy go zaimplementować:

[ContentProperty("ResId")]
public class LocalizeExtension : IMarkupExtension
{
	public string ResId { get; set; }
	static CultureInfo ci = null;

	public LocalizeExtension()
	{
		if (ci == null && (Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android))
		{
			ci = DependencyService.Get<ILocaleService>().GetCurrentCultureInfo();
		}
	}

	public object ProvideValue(IServiceProvider serviceProvider)
	{
		if (string.IsNullOrWhiteSpace(ResId))
			return "<???>";

		string result = LangRes.ResourceManager.GetString(ResId, ci);
		if (string.IsNullOrEmpty(result))
			return $"<? {ResId} ?>";
		else
			return result;
	}
}

Klasa trzyma CultureInfo, które jest pobrane z jakiegoś serwisu. Jest to potrzebne tylko na Androidzie i iOS. Kto bardziej spostrzegawczy, to zorientuje się, że moja metoda ProvideValue ma mały błąd. Tak naprawdę powinienem też w niej sprawdzić platformę i albo wykorzystać metodę GetString z przeciążeniem CultureInfo (dla Androida i iOS), albo wersję bez CultureInfo. Jednak w Xamarinie robię tylko pod Androida, więc darowałem sobie to sprawdzenie.

Atrybut ContentProperty ustawiony na klasie wskazuje na domyślną właściwość. Dzięki czemu w XAML nie musimy już jej podawać:

<Label Text="{app:Localize ResId=Receipt}"/>

wystarczy:

<Label Text="{app:Localize Receipt}"/>

No dobrze, ale co z tym serwisem ILocaleService?

Pobranie lokalizacji z Androida i iOS

Xamarin wymaga jednego małego myku. Każdy z tych systemów musi sam zwrócić odpowiednią lokalizację. Zatem idealnym wydaje się utworzenie interfejsu i jego implementacja w konkretnym projekcie (nie ogólnym Xamarin, tylko konkretnie w aplikacji Android i iOS). Interfejs jest prosty:

Tworzenie ILocaleService

Zdefiniuj ten interfejs gdzieś w projekcie Xamarina lub w projekcie współdzielonym przez projekty Xamarina.

public interface ILocaleService
{
	CultureInfo GetCurrentCultureInfo();
	void SetLocale(CultureInfo ci);
}

Tworzenie PlatformCulture

Teraz musimy utworzyć małą klasę pomocniczą też w projekcie Xamarin (lub współdzielonym). Powinna ona wyglądać tak:

public class PlatformCulture
 {
	public PlatformCulture(string platformCultureString)
	{
		if (String.IsNullOrEmpty(platformCultureString))
			throw new ArgumentException("Expected culture identifier", nameof(platformCultureString)); 

		PlatformString = platformCultureString.Replace("_", "-"); // .NET expects dash, not underscore
		var dashIndex = PlatformString.IndexOf("-", StringComparison.Ordinal);
		if (dashIndex > 0)
		{
			var parts = PlatformString.Split('-');
			LanguageCode = parts[0];
			LocaleCode = parts[1];
		}
		else
		{
			LanguageCode = PlatformString;
			LocaleCode = "";
		}
	}
	public string PlatformString { get; private set; }
	public string LanguageCode { get; private set; }
	public string LocaleCode { get; private set; }
	public override string ToString()
	{
		return PlatformString;
	}
}

To jest kod wzięty z oficjalnej dokumentacji Microsoftu. Zadanie tej klasy stanie się za chwilę bardziej jasne. Generalnie jej celem jest właściwie zwrócenie kodu kraju, jeśli dostaniemy z urządzenia kod, którego nie ma w .NET, np. „en-ES”.

Implementacja ILocaleService na Androidzie

Po tych wszystkich znojach, musimy teraz utworzyć klasę w projekcie Androida, która będzie implementowała interfejs ILocaleService:

using System.Globalization;
using System.Threading;
using Xamarin.Forms;

[assembly: Dependency(typeof(Xamarin.Droid.Services.LocaleService))]
namespace Xamarin.Droid.Services
{
    public class LocaleService : ILocaleService
	{
		public CultureInfo GetCurrentCultureInfo()
		{
			var netLanguage = "en";
			var androidLocale = Java.Util.Locale.Default;
			netLanguage = AndroidToDotnetLanguage(androidLocale.ToString().Replace("_", "-"));
			// this gets called a lot - try/catch can be expensive so consider caching or something
			CultureInfo ci = null;
			try
			{
				ci = new CultureInfo(netLanguage);
			}
			catch (CultureNotFoundException)
			{
				// iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
				// fallback to first characters, in this case "en"
				try
				{
					var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
					ci = new CultureInfo(fallback);
				}
				catch (CultureNotFoundException)
				{
					// iOS language not valid .NET culture, falling back to English
					ci = new CultureInfo("en");
				}
			}
			return ci;
		}

		public void SetLocale(CultureInfo ci)
		{
			Thread.CurrentThread.CurrentCulture = ci;
			Thread.CurrentThread.CurrentUICulture = ci;
		}

		string AndroidToDotnetLanguage(string androidLanguage)
		{
			var netLanguage = androidLanguage;
			//certain languages need to be converted to CultureInfo equivalent
			switch (androidLanguage)
			{
				case "ms-BN":   // "Malaysian (Brunei)" not supported .NET culture
				case "ms-MY":   // "Malaysian (Malaysia)" not supported .NET culture
				case "ms-SG":   // "Malaysian (Singapore)" not supported .NET culture
					netLanguage = "ms"; // closest supported
					break;
				case "in-ID":  // "Indonesian (Indonesia)" has different code in  .NET
					netLanguage = "id-ID"; // correct code for .NET
					break;
				case "gsw-CH":  // "Schwiizertüütsch (Swiss German)" not supported .NET culture
					netLanguage = "de-CH"; // closest supported
					break;
					// add more application-specific cases here (if required)
					// ONLY use cultures that have been tested and known to work
			}
			return netLanguage;
		}
		string ToDotnetFallbackLanguage(PlatformCulture platCulture)
		{
			var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
			switch (platCulture.LanguageCode)
			{
				case "gsw":
					netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
					break;
					// add more application-specific cases here (if required)
					// ONLY use cultures that have been tested and known to work
			}
			return netLanguage;
		}
	}
}

Z urządzenia dostaniemy kod kraju w postaci en_US – z podkreślnikiem zamiast myślnika. Dlatego też w pierwszej kolejności trzeba to zmienić.

Następnie trzeba spróbować utworzyć CultureInfo z przekazanym kodem. Niestety, może się okazać że z urządzenia otrzymamy kod, którego nie ma w .NET (jak wyżej wspomniany en-ES). I tu wchodzi do roboty klasa PlatformCulture, która po prostu sparsuje odpowiednio kod kraju i zwróci tylko identyfikator języka (np. „en”).

Ten kod również pochodzi z oficjalnej dokumentacji Microsoftu. Przyjrzyj się jeszcze linijce nr 5:

[assembly: Dependency(typeof(Xamarin.Droid.Services.LocaleService))]

To po prostu mechanizm DependencyInjection, którym posłużymy się jeszcze za chwilę. I którym posługujemy się w konstruktorze Xamarinowego LocalizeExtension. Ten atrybut automagicznie rejestruje klasę.

Implementacja ILocaleService na iOS

Nie musisz tego robić, jeśli nie piszesz aplikacji pod iOS. Jeśli jednak ma działać na jabłuszku, jest to konieczne. Poniższy kod jest podobny do tego z Androida i też pochodzi z oficjalnej dokumentacji Microsoftu:

assembly: Xamarin.Forms.Dependency(typeof(Xamarin.iOS.Services.LocaleService))]
namespace Xamarin.iOS.Services
{
	//https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/localization/text?tabs=windows

	public class LocaleService : ILocaleService
	{
		public CultureInfo GetCurrentCultureInfo()
		{
			var netLanguage = "en";
			if (NSLocale.PreferredLanguages.Length > 0)
			{
				var pref = NSLocale.PreferredLanguages[0];
				netLanguage = iOSToDotnetLanguage(pref);
			}
			// this gets called a lot - try/catch can be expensive so consider caching or something
			CultureInfo ci = null;
			try
			{
				ci = new CultureInfo(netLanguage);
			}
			catch (CultureNotFoundException )
			{
				// iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
				// fallback to first characters, in this case "en"
				try
				{
					var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
					ci = new CultureInfo(fallback);
				}
				catch (CultureNotFoundException )
				{
					// iOS language not valid .NET culture, falling back to English
					ci = new CultureInfo("en");
				}
			}
			return ci;
		}

		public void SetLocale(CultureInfo ci)
		{
			Thread.CurrentThread.CurrentCulture = ci;
			Thread.CurrentThread.CurrentUICulture = ci;
		}

		string iOSToDotnetLanguage(string iOSLanguage)
		{
			// .NET cultures don't support underscores
			string netLanguage = iOSLanguage.Replace("_", "-");

			//certain languages need to be converted to CultureInfo equivalent
			switch (iOSLanguage)
			{
				case "ms-MY":   // "Malaysian (Malaysia)" not supported .NET culture
				case "ms-SG":    // "Malaysian (Singapore)" not supported .NET culture
					netLanguage = "ms"; // closest supported
					break;
				case "gsw-CH":  // "Schwiizertüütsch (Swiss German)" not supported .NET culture
					netLanguage = "de-CH"; // closest supported
					break;
					// add more application-specific cases here (if required)
					// ONLY use cultures that have been tested and known to work
			}
			return netLanguage;
		}

		string ToDotnetFallbackLanguage(PlatformCulture platCulture)
		{
			var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
			switch (platCulture.LanguageCode)
			{
				case "pt":
					netLanguage = "pt-PT"; // fallback to Portuguese (Portugal)
					break;
				case "gsw":
					netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
					break;
					// add more application-specific cases here (if required)
					// ONLY use cultures that have been tested and known to work
			}
			return netLanguage;
		}
	}
}

Ustawienie kultury

Teraz w pliku App.xaml.cs w projekcie Xamarin powinieneś dodać gdzieś podczas inicjalizacji taki fragment kodu:

if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android)
{
	var ci = DependencyService.Get<ILocaleService>().GetCurrentCultureInfo();
	LangRes.Culture = ci;
	DependencyService.Get<ILocaleService>().SetLocale(ci);
}

Gdzie LangRes to Twoja klasa z zasobami utworzona przez VisualStudio. Wszystko to ma na celu zapewnienie poprawnego działania lokalizacji na urządzeniach z Androidem i iOS.

Jak tłumaczyć w XAML?

Tutaj sprawa wygląda już dokładnie tak samo jak przy WPF. Wystarczy, że zadeklarujesz alias na swój namespace w pliku xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:app="clr-namespace:MojaAplikacja"

gdzie MojaAplikacja to namespace do klasy LocalizeExtension; następnie w kodzie:

<Label Text="{app:Localize Receipt}"/>

gdzie Receipt to po prostu klucz z zasobów językowych.


To na tyle jeśli chodzi o tłumaczenia aplikacji na urządzeniach mobilnych. Jeśli używasz jakiegoś innego sposobu lub znalazłeś błąd w artykule, koniecznie podziel się w komentarzu 🙂

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: