Monthly Archives: July 2019

O tym jak stworzyłem… stronę z kamperami!

W 2019 roku w ciągu 2 miesięcy stworzyłem stronę bookacamper.pl, największą w Polsce tablicę ogłoszeń o wynajmie i sprzedaży przyczep kempingowych i kamperów. Strona jest całkowicie darmowa i ma po prostu pomóc w odnalezieniu tego jedynego, najlepszego pojazdu:)

Narodziny miłości do kempingów

Od czasu kiedy pierwszy raz wypożyczyłem kampera i poleciałem z rodziną do odległej Kanady, zakochałem się w tym sposobie na wakacje. Być może to ta niezależność podróżowania, bo możesz dojechać na kemping i jak Ci się nie spodoba, to jedziesz na następny. Może to rewelacyjna infrakstruktura – w Kanadzie aż roi się od kempingów, a niemalże obok co drugiego domu dostrzegaliśmy przyczepę kempingową. Do tego widoki i przepiękna przyroda zapiera dech w piersiach. A może po prostu coś szalonego, nowego i nierealnego na pierwszy rzut oka. No bo z dwójką małych dzieci i trzecim w drodze na inny kontynent? Chyba macie już przed oczyma naszych bliskich, którzy co chwilę dopytywali co żeśmy sobie wymyślili 🙂

Wspomnienie przygody

W Kanadzie spędziliśmy prawie 3 tygodnie i zabraliśmy ze sobą wspaniałe wspomnienia, a także chęć, żeby to kiedyś powtórzyć. W tym roku zaczęliśmy obmyślać następną wyprawę… postanowiliśmy, że wypożyczymy przyczepę i zwiedzimy Europę, ponownie całą rodzinką, tylko tym razem już w piątkę.

Zacząłem szukać wypożyczalni przyczep kempingowych i owszem, w Wielkopolsce jest ich kilka, jednak ciężko mi było te oferty porównać, wyszukać w wygodny sposób. Stąd pomysł, żeby zrobić jedno miejsce, gdzie mógłbym przeglądać wszystkie ogłoszenia. To chyba nie może być takie trudne, co nie?

Wybór technologii

Na codzień jestem programistą. Co więcej – zajmuję się pisaniem dużych sklepów internetowych. Co więc mogło być pierwszą myślą, jaka mi zakiełkowała w głowie?

Nie chcę tego sam pisać od początku, to za dużo pracy!

Słyszałem, że pół Internetu działa na WordPress i miałem z nim już do czynienia. Był to więc naturalny wybór, co więcej, ten blog jest postawiony właśnie na WP!

WordPress to darmowy gotowy silnik do blogowania oraz do każdego innego biznesu jaki jesteś w stanie sobie wyobrazić. WP to podstawowy system, który postawisz dosłownie w kilka minut oraz gigantyczna społeczność, która go rozwija.

Czy WordPress jest darmowy?

Jak powiedziałby dobry konsultant – to zależy. Po pierwsze zależy to od tego, czy masz własny hosting. Możesz użyć gotowego, darmowego hostingu na wordpress.com i zacząć bez kosztów. Nie będziesz jednak mógł instalować pluginów, przez co możliwość dostosowania wyglądu i finkcjonalności strony jest dość mocno ograniczona. No chyba że wykupisz konto płatne, które pozwala na więcej.

Najlepiej moim zdaniem jest wykupić hosting WordPress, gdzie postawienie strony potrwa kilka minut, jednak to jakie pluginy zainstalujesz będzie zależało od Ciebie. Ze swojej strony mogę polecić hosting na Webio.pl, gdzie jest postawiony ten blog. Działa bez zarzutów 🙂

Jak zatem mogą się szacować koszty roczne? Moim zdaniem minimum to ok. 100zł rocznie za hosting i ok 20-100zł rocznie za domenę. Warto dobrze przemyśleć nazwę swojej domeny, ponieważ nasza strona będzie z nią nieodzownie związana.

Potrzebuję czegoś więcej niż blog

Co prawda posty na blogu możesz zacząć pisać od razu, jednak żeby przerobić WP na sklep internetowy z torebkami, tablicę ogłoszeń wędkarskich, a może agencję matrymonialną dla kotów – musisz doinstalować wtyczkę(plugin).

Widok ogłoszeń dzięki wtyczce Wp Adverts

I tutaj zaczyna się prawdziwa praca – szukanie odpowiedniego dodatku może zająć dni, a nawet tygodnie. Większość dodatków można zobaczyć w praktyce na stronach twórców, a także zainstalować i oddać w ciągu 30 dni, jeżeli jednak nie o to Ci chodziło.

Do swojego projektu ostatecznie wybrałem serię dodatków WP Adverts, możesz zobaczyć wersję demonstracyjną tutaj:
https://demo.wpadverts.com/lite/adverts/. Wtyczka ta pozwala na stworzenie tablicy ogłoszeń, oraz:

  • łatwe dodanie ogłoszenia z formularza oraz jego edycja
  • dodanie lokalizacji ogłoszeń oraz wyświetlenie map Google z lokalizacją
  • dodanie weryfikacji reCaptacha, żeby zabezpieczyć dodawanie ogłoszeń
  • konfigurowane kategorie (u mnie jest to sprzedaż przyczep, wynajem przyczep, sprzedaż kamperów oraz wynajem kamperów
  • dodanie własnych pól do ogłoszeń – mogłem dodać DMC czy długość przyczepy
  • formularz do szukania ogłoszeń, także po lokalizacji oraz po własnych polach, jak np. rok produkcji
Bogate wyszukiwanie po niestandardowych polach

W tym wypadku twórcy dodatku udzielają rewelacyjnego wsparcia – mogę potwierdzić. Podczas konfiguracji strony miałem parę pytań i uzyskałem odpowiedź w kilka godzin!

Jakie mam zainstalowane wtyczki?

Wtyczki w WordPress są do wszystkiego, dosłownie. Jeżeli chcesz zmienić coś na stronie, to po prostu wyszukujesz odpowiednią wtyczkę i jej używasz. Proste. Oto te, które mi się przydają najbardziej:

  • WP Adverts – seria wtyczek do obsługi ogłoszeń na stronie. Jedyna płatna wtyczka na liście
  • Loco Translate – pozwala przetłumaczyć WP Adverts na język polski
  • Contact Form 7 – tworzy prosty formularz do kontaktu
  • Facebook Widget – integruje stronę z Facebook, widać ile osób lubi naszą stronę. Można też pokazać ostatnie posty
  • Informacja o ciasteczkach – informacja na dole strony, że strona używa ciasteczek
  • LoginPress – Customizing the WordPress Login – pozwala dostosować stronę logowania, żeby pasowała do naszej strony
  • Really Simple SSL – dzięki niej SSL i linki działają poprawnie
  • Akismet antyspam – blokuje spam przychodzący z formularza kontaktowego oraz komentarzy
  • GA Google Analytics – pozwala skonfigurować Google Analytics na stronie

Wtyczek jest dość sporo i jest to też dość pracochłonne, żeby je skonfigurować. Czasami zajmowało mi to kilka minut, a innym razem kilka godzin lub dni, zanim rozwiązałem problem.

Inną przeszkodą może być to, że większość wtyczek jest opisana po angielsku i bez znajomości tego języka dużo trudniej będzie Ci przeglądać chociażby dokumentację, bądź szukać odpowiedzi na forach internetowych.

Czy mogę dowolnie zmieniać wygląd strony?

W skrócie – tak. Fantastyczną możliwością jest to, że można skorzystać z gotowych motywów dostępnych za darmo, lub za opłatą.

Testowanie różnych motywów jest bardzo wygodne, ponieważ wystarczy wybrać motyw i zastosować go na próbę na swojej stronie. Strona zmieni swój układ i wygląd, ale treści i obrazki pozostaną bez zmian.

Diabeł tkwi w szczegółach. Motywy są piękne, kolory są świetnie dobrane i dobrze wyświetlają się na komórce, jednak mają swoje ograniczenia. Kiedy chcemy aby np. nagłówek lub menu wyglądało trochę inaczej, a nie da się tego zmienić za pomocą wbudowanych opcji, pozostaje nam edycja manualna. Każdy motyw pozwala na edycję HTML-a i CSS-a, więc teoretycznie można zmienić wszystko, ale nie jest to najłatwiejsze.

Co warto zrobić

Jest kilka rzeczy, które najlepiej skonfigurować i załatwić od razu.

  • Skrzynka pocztowa z adresem zgodnym z domeną strony – należy skonfigurować pocztę na serwerze gdzie jest postawiona strona, żeby WordPress mógł wysyłać wiadomości e-mail z formularza kontaktowego
  • Dodać certyfikat SSL – to dodatkowa usługa, którą trzeba wykupić, aby przy adresie naszej strony pojawiła się ‘kłódka’. Potwierdza to że strona jest bezpieczna i posiada ważny certyfikat
  • Poszukaj podobnych stron. Prawdopodobnie stron takich jak Twoja jest kilkanaście w Internecie i z pewnością czymś się różnią. Poprzeglądaj je i zobacz, jakie elementy sprawdzą się najlepiej u Ciebie
  • Żyj w zgodzie z sieciami społecznościowymi. Facebook, Instagram i LinkedIn to genialne narzędzia do promowania siebie i swojego biznesu. Kiedy szukam np. restauracji po nazwie niemalże zawsze trafiam na Facebook, gdzie jest cała społeczność zgromadzona na fanpage-u danego lokalu. Publikuj treści i promuj się. W moim przypadku duża część ruchu trafia na moje strony właśnie z sieci społecznościowych

Próbuj, to nic nie kosztuje*

Stworzenie podstawowej strony na WordPress jest dziecinnie proste. Może to być Twój blog, może mały biznes albo sklep internetowy. Ważne, żeby było to coś, co naprawdę lubisz. Z własnego doświadczenia wiem, że blogowanie przynosi niesamowitą satysfakcję.

*stworzenie strony na WordPress może kosztować kilkaset złotych, jednak głównie jest to Twój poświęcony czas, a ten zawsze się znajdzie.

Mnie do działania zachęcił ten TED talk:

Mam nadzieję, że tym postem zmotywowałem Cię do działania i przekonałem, że realizowanie chociażby najśmielszych przedsięwzięć nie musi być wcale takie trudne. Powoli obserwuję, że na bookacamper.pl wchodzi coraz więcej osób i to bardzo cieszy. Jeżeli spodobała Ci się ta strona i jesteś fanem campingów tak jak ja, to daj znać. Pomoc w rozwoju strony zawsze się przyda!

Także do dzieła i powodzenia! 🙂

Code review #4 – in-memory caching

This is a post on a series about great code review feedback, that I either gave or received. You can go ahead and read the previous ones here: https://www.michalbialecki.com/2019/06/21/code-reviews/

The context

Caching is an inseparable part of ASP.net applications. It is the mechanism that makes our web pages loading blazing fast with a very little code required. However, this blessing comes with responsibility. I need to quote one of my favorite characters here:

Downsides come into play when you’re no longer sure if the data that you see are old, or new. Caches in different parts of your ecosystem can make your app inconsistent, incoherent. But let’s not get into details since it’s not the topic of this post.

Let’s say we have an API, that gets user by id and code looks like this:

[HttpGet("{id}")]
public async Task<JsonResult> Get(int id)
{
    var user = await _usersRepository.GetUserById(id);
    return Json(user);
}

Adding in-memory caching in .net core is super simple. You just need to add one line in the Startup.cs

And then pass IMemoryCache interface as a dependency. Code with in-memory caching would look like this:

[HttpGet("{id}")]
public async Task<JsonResult> Get(int id)
{
    var cacheKey = $"User_{id}";
    if(!_memoryCache.TryGetValue(cacheKey, out UserDto user))
    {
        user = await _usersRepository.GetUserById(id);
        _memoryCache.Set(cacheKey, user, TimeSpan.FromMinutes(5));
    }

    return Json(user);
}

Review feedback

Why don’t you use IDistributedCache? It has in-memory caching support.

Explanation

Distributed cache is a different type of caching, where data are stored in an external service or storage. When your application scales and have more than one instance, you need to have your cache consistent. Thus, you need to have one place to cache your data for all of your app instances. .Net net code supports distributed caching natively, by IDistributedCache interface.

All you need to do is to change caching registration in Startup.cs:

And make a few modifications in code using the cache. First of all, you need to inject IDistributedCache interface. Also remember that your entity, in this example UserDto, has to be annotated with Serializable attribute. Then, using this cache will look like this:

[HttpGet("{id}")]
public async Task<JsonResult> Get(int id)
{
    var cacheKey = $"User_{id}";
    UserDto user;
    var userBytes = await _distributedCache.GetAsync(cacheKey);
    if (userBytes == null)
    {
        user = await _usersRepository.GetUserById(id);
        userBytes = CacheHelper.Serialize(user);
        await _distributedCache.SetAsync(
            cacheKey,
            userBytes,
            new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(5) });
    }

    user = CacheHelper.Deserialize<UserDto>(userBytes);
    return Json(user);
}

Using IDistributedCache is more complicated, cause it doesn’t support strongly types and you need to serialize and deserialize your objects. To not mess up my code, I created a CacheHelper class:

public static class CacheHelper
{
    public static T Deserialize<T>(byte[] param)
    {
        using (var ms = new MemoryStream(param))
        {
            IFormatter br = new BinaryFormatter();
            return (T)br.Deserialize(ms);
        }
    }

    public static byte[] Serialize(object obj)
    {
        if (obj == null)
        {
            return null;
        }

        var bf = new BinaryFormatter();
        using (var ms = new MemoryStream())
        {
            bf.Serialize(ms, obj);
            return ms.ToArray();
        }
    }
}

Why distributed cache?

Distributed cache has several advantages over other caching scenarios where cached data is stored on individual app servers:

  • Is consistent across requests to multiple servers
  • Survives server restarts and app deployments
  • Doesn’t use local memory

Microsoft’s implementation of .net core distributed cache supports not only memory cache, but also SQL Server, Redis and NCache distributed caching. It all differs by extension method you need to use in Startup.cs. This is really convenient to have caching in one place. Serialization and deserialization could be a downside, but it also makes it possible to make a one class, that would handle caching for the whole application. Having one cache class is always better then having multiple caches across an app.

When to use distributed memory cache?

  • In development and testing scenarios
  • When a single server is used in production and memory consumption isn’t an issue

If you would like to know more, I strongly recommend you to read more about:

  All code posted here you can find on my GitHub: https://github.com/mikuam/Blog

Postman the right way

Postman is a great tool to quickly create a request and run it against your API. This is a flexible tool created to make your work simpler. You can save you requests, define variables for different environments and share it with your team. Today I’ll show you the most useful and practical features of Postman.

Swagger is not good enough

Swagger is an API package, that eases working with API. It comes almost out of the box. With a little configuration, it exposes user-friendly interface alongside with your API. Postman, on the other hand, is an external tool to make requests to your API but does not interfere with it. It comes in handy in cases where Swagger is not enough. What’s the main advantage of using it is the fact, that you can store your requests and you don’t need to fill in the data for the request over and over again. In fact, both tools are great and can be used together, but with a slightly different purpose.

Let’s look at the example. This is how swagger looks under .net core:

And this is a Postman window with the same request:

Comparing to Swagger, Postman is much more compact and because it is an external tool, it offers much more.

The best things

I won’t list the whole documentation here, but I’m going to show you what I like the most and what I use on a day to day basis.

Simply provide authorization

In the Authorization tab you can easily define what you need and it will be added to you request. It supports whole list of authorization methods and frankly, I only used a few of them. For example if you need to provide basic authorization, you just need to put user and password, without a need to encode it in base64 manually.

Save request to a collection

Next, to the Send button, there is an option to save a request and put it in the collection. If you have different micro-services you work on, you can divide your requests by service, or by context and put them into different collections. You can even create nested folders to make separation of requests even greater.

Add variables

The great thing that I discovered recently is an ability to define your own variables. To do this you need to click settings icon on the right and choose Globals button at the bottom of a popup.

Then you will be able to define variables you can use later. I added a url for my service(document-service-url), since I will be using that in every request for my service.

You can use your variable, by putting its name in a double curly braces like in the image above. This is very convinient when suddenly you need to change a port in your url or a password in the basic authorization method.

Define environments

As you saw, the URL that I used is defined by variable, that I can use in every request, but only locally. What about other environments? Postman support that as well. To add an environment, just click on the settings icon on the right and add one.

Now when I choose Development environment, the value of my variable will be different.

Share you requests across the team

This is all great, but how can you send a request to a friend, so he can use it as well? The easiest this is export entire collection as a json file and you colleague can import it in his Postman.

The other thing that you can do is to share you collection. On the top there is a My workspace dropdown, where you can define teams.

Once you click on a team, Postman will load all of the teams collctions. Great thing about it is, that you can work with the same requests within a one team and keep them up to date as the work goes. This was a real game changer for me and in fact a motivation to write this post! There is however a little drawback – in a free version, you can only share 25 requests across the team, and this is not a lot.

To sum up – I am very impressed by Postman and the possibilities that it offers. It actually offers much more then I mentioned. I also like its visual side and simplicity. I hope you like it too 🙂