Blog Dla Młodszych Programistów C#/.NET

Jeżeli zaczynasz naukę programowania w ASP.NET Core, to na początku możesz się spotkać z różnymi problemami, natomiast warto z czasem uczyć się na błędach, nie tylko swoich i wyciągać z nich wnioski. Jest to najlepszy sposób nauki. W tym artykule przedstawię Ci właśnie 8 błędów początkujących programistów, które popełniają pisząc aplikacje w ASP.NET Core. Mam nadzieję, że dzięki temu materiałowi nie będziesz ich powtarzał w swoich aplikacjach.

8 Popularnych Błędów Początkujących w ASP.NET Core

Błąd 1: Zbyt duże akcje w kontrolerach


Twoje akcje w kontrolerach powinny być jak najmniejsze, powinieneś tylko zrobić walidację przesłanych danych, następnie wywołać jakaś metodą w której jest logika np. z jakiegoś serwisu lub warstwy aplikacji najlepiej za pomocą mediatr i zwrócić na podstawie tych danych odpowiedni widok z modelem. Nie umieszczaj tutaj żadnego dodatkowe kodu, nie twórz żadnej logiki, instrukcji warunkowych czy pętli wewnątrz akcji kontrolera, to nie jest jego odpowiedzialność.

Źle:
public IActionResult Contact()
{
    var model = _context.Params.ToList();

    if (model == null)
        return RedirectToAction("Contact");

    if (model.First().IsDisabled)
    {
        foreach (var item in model)
        {
            item.Date = _dateTimeService.Now;
        }
    }

    var availableTemplates = _context.Templates.ToList();

    ViewBag.Title = "Kontakt";

    var vm = new ContactVm
    {
        model = model,
        availableTemplates = availableTemplates
    };

    return View(vm);
}

Dobrze:
public IActionResult Contact()
{
    return View(new SendContactEmailCommand());
}


Błąd 2: Logika w widokach


W widokach, które w mvc tworzymy w razorze nie powinno być żadnej logiki. Jeżeli chcesz pobrać jakieś dane, wykonać jakąś inną logikę, to nie powinien się tym zajmować widok. Ta logika powinna zostać wykonana wcześniej w warstwie aplikacji i zostać przekazana z kontrolera do widoku za pomocą modelu lub view modelu. Przez logikę wykonywaną w warstwie widoku nasza aplikacja staje się mniej czytelna i tworzy się tzw. spaghetti code.

Źle:
Client.cshtml
@model ClientDo

@{
    ViewData["Title"] = "Klient";
}

@if (Model.Id == 0)
{
    <div>Dodawanie klienta</div>
}
else
{
    <div>Edytowanie danych klienta</div>
}

Dobrze:
Client.cshtml
@model ClientVm

@{
    ViewData["Title"] = "Klient";
}

<div>@Model.Title</div>


Błąd 3: Brak obiektów DTO


Pamiętaj, żeby nie zwracać użytkownikowi całych modelów domenowych. Dużo lepszą praktyką jest utworzenie w takim przypadku obiektów DTO. Użytkownik nie potrzebuje wszystkich informacji o naszym modelu. Zwróć tylko to, co faktycznie jest potrzebne na widoku, czy też w API. Dzięki obiektom DTO masz większą kontrolę nad tym co będzie zwracane z akcji i możesz odpowiednio przygotować i dostosować wszystkie dane.

Źle:
public class Client
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public DateTime RegistrationDate { get; set; }
    public bool IsDeleted { get; set; }
    public bool IsActive { get; set; }
    public List<Order> Orders { get; set; }
    public Address Address { get; set; }
}

public class GetClientQuery : IRequest<Client>
{
}

public async Task<IActionResult> Dashboard()
{
    return View(await Mediator.Send(new GetClientQuery()));
}

Dobrze:
public class ClientDto
{
    public string FullName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public bool IsActive { get; set; }
}

public class GetClientQuery : IRequest<ClientDto>
{
}

public async Task<IActionResult> Dashboard()
{
    return View(await Mediator.Send(new GetClientQuery()));
}


Błąd 4: Złe przekazywanie danych do widoku


Jeżeli chcesz przekazać z kontrolera do widoku więcej danych niż tylko sam model, to możesz to zrobić na kilka sposobów. To znaczy możesz przekazać bezpośrednio model, a dodatkowe dane np. poprzez ViewBaga czy ViewData. Natomiast nie jest najlepsze rozwiązanie, wprowadza trochę nieporządku w kodzie, dlatego dużo lepszym rozwiązaniem w takim przypadku będzie utworzenie dedykowanego view modelu i przekazanie wszystkich danych poprzez view model. Właśnie dla takich przypadków idealnie się one nadają, dlatego powinniśmy z tego korzystać. W łatwy sposób możemy później odwołać się do view modelu w naszym widoku.

Źle:
public class GetClientDashboardQuery : IRequest<ClientDto>
{
}

public async Task<IActionResult> Dashboard()
{
    ViewBag.Title = "Pulpit klienta";
    ViewBag.Now = _dateTimeService.Now;
    ViewBag.City = "Warszawa";
    ViewBag.Email = "kazimierz.szpin@modestprogrammer.pl";
    return View(await Mediator.Send(new GetClientDashboardQuery()));
}

Dobrze:
public class GetClientDashboardQuery : IRequest<GetClientDashboardVm>
{
}

public async Task<IActionResult> Dashboard()
{
    return View(await Mediator.Send(new GetClientDashboardQuery()));
}


Błąd 5: Brak walidacji danych użytkownika


Nigdy nie możesz ufać użytkownikowi swojej aplikacji i na każdym kroku powinieneś sprawdzać dane, które wprowadził. Zawsze stosuj walidację wprowadzanych przez niego danych. Jeżeli dane nie spełnią warunków walidacji, to zamiast rzucać wyjątkiem lub powodować jakieś błędy, powinieneś wyświetlić odpowiedni komunikat.

Źle:
[HttpPost]
public async Task<IActionResult> Contact(SendContactEmailCommand command)
{
    await Mediator.Send(command);

    return RedirectToAction("Contact");
}

Dobrze:
[HttpPost]
public async Task<IActionResult> Contact(SendContactEmailCommand command)
{
    if (!ModelState.IsValid)
        return View(command);

    await Mediator.Send(command);

    return RedirectToAction("Contact");
}


Błąd 6: Używanie nieodpowiednich kontrolek na widoku


To jest dość często spotykany błąd, który popełniają głównie osoby początkujące. Jeżeli chcesz, aby użytkownik wprowadził datę, to zamiast wprowadzać ją np. na TextBoxie, pozwól mu ją wybrać na dedykowanej kontrolce, czyli w tym przypadku na jakimś DateTimePickerze. Oprócz tego, że użytkowniki będzie łatwiej wybrać konkretną datę na kalendarzu, to również zapobiegniesz dzięki temu różnych błędów walidacyjnych. Tak samo jeżeli chcesz, żeby użytkownik wprowadził wartość true/false, to wyświetl CheckBox lub Switcha, jeżeli ma wprowadzić liczbę, czy kwotę to również wyświetl mu odpowiednią kontrolkę, nie zawsze TextBox jest odpowiednią kontrolką do wprowadzania wszystkich danych.

Źle:
Popularne Błędy Początkujących w ASP.NET Core - złe kontrolki

Dobrze:
Popularne Błędy Początkujących w ASP.NET Core - dobre kontrolki


Błąd 7: Złe używanie HttpClienta


Najlepszym sposobem w aplikacji ASP.NET Core jest używanie HttpClienta przez fabrykę, czyli stosowanie interfejsu IHttpClientFactory. Jeżeli tworzysz nowy obiekt HttpClient bez w standardowy sposób bez używania fabryki, to generuje to 2 problemy. Po pierwsze obiekty nie są odpowiednio usuwane, a po drugie mogę powodować wyczerpanie zasobów, ponieważ każdy obiekt tak naprawdę tworzy nowy socket i nawet użycie usinga nie zwolni nam od razu tego socketa. Jeżeli chciałbyś stworzyć obiekt HttpClient jako singleton lub static, to z kolei mogą pojawić się problemy z nieaktualnym DNS, także jedynym dobrym rozwiązaniem jest stosowanie IHttpClientFactory, dzięki któremu unikniemy tych błędów.

Źle:
HttpClient httpClient = new HttpClient();

using (HttpClient httpClient = new HttpClient())
{
}

Dobrze:
HttpClientFactory

services.AddHttpClient<SomInterface, SomeClass>();

public SomeClass(HttpClient httpClient)
{
    _httpClient = httpClient;
}


Błąd 8: Oczekiwanie na niepotrzebne i długotrwałe operacje


Jeżeli użytkownik chcę wykona jakąś akcję, po której wymagane jest wywołanie jakiejś długotrwałej operacji, a dodatkowo jeszcze wynik jej działania nie jest dla niego istotny, to powinieneś taką operację wykonać w tle i nie kazać czekać użytkownikowi na zakończenie tej operacji. Dzięki temu nie będzie przez kilka sekund wisiał jego request, a aplikacja będzie działać płynnie. Kiedy to może mieć zastosowanie? Np. wtedy gdy użytkownik wykonał jakąś akcję, a dodatkowo zostaje wysłany email do administratora. W niektórych bibliotekach oczekiwanie na wysłanie maila może wynosić około sekundy, także nie ma potrzeby żeby użytkownik oczekiwał na zakończenie tego zadania. Po prosty zakończ request, a maila wyślij w tle. W ASP.NET Core możesz to osiągnąć na kilka sposobów np. poprzez implementacje klasy dziedziczącej po BackgroundService i dodanie jej do aplikacji jako HostedService.

public interface IBackgroundWorkerQueue
{
    void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);
}

public class LongRunningService : BackgroundService
{
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        //kod
    }
}

services.AddHostedService<LongRunningService>();
services.AddSingleton<IBackgroundWorkerQueue, BackgroundWorkerQueue>();

_backgroundWorkerQueue.QueueBackgroundWorkItem(async x =>
{
    await _email.SendAsync(title, admin, to);

});


Szkoła ASP.NET Core


Jeżeli interesują Cię tematy z tworzeniem profesjonalnych aplikacji webowych w ASP.NET Core, to rozważ dołączenie do: Szkoły ASP.NET Core. Jest to zaawansowane praktyczne szkolenie ASP.NET Core MVC + REST API dla Programistów C#/.NET. Szkolenie składa się z 14 rozbudowanych modułów. W szkoleniu tworzymy kompletną aplikację w ASP.NET Core od pierwszych linii kodu, aż po wdrożenie w chmurze (więcej tutaj).

To wszystkie na dzisiaj. Jeżeli taki artykuł Ci się spodobał, to koniecznie dołącz do mojej społeczności – darmowe zapisy, gdzie będziesz również miał dostęp do dodatkowych materiałów i przede wszystkim bonusów. Do zobaczenia w kolejnym artykule.

Poprzedni artykuł - Jak Zostać Freelancerem i Pracować Na Własnych Warunkach Jako Programista?
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
Programista C#/.NET. Specjalizuje się w ASP.NET Core, ASP.NET MVC, ASP.NET Web API, Blazor, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Dodaj komentarz

Wyszukiwarka

© Copyright 2022 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Polityka prywatności. Design by Kazimierz Szpin