ASP.NET vNext on Ubuntu Linux

Disclaimer: Please note that this description is made based on taken notes during installation and is a subject to change after additional verification.

Described installation has been made on Ubuntu 14.04.

In first step let’s update packages information using:

sudo apt-cache update

Next step is installation of Mono prerequisites:

sudo apt-get install git autoconf libtool automake build-essential mono-devel gettext libuv0.10

Then clone Mono repository from GitHub to selected folder, install it and verify instalation:

mkdir mono
cd mono
git clone
https://github.com/mono/mono.git

Change directory in order to execute autogen.sh script

./autogen.sh –prefix=/usr/local && make && sudo make install

And check Mono version using:

mono –version

By default this version of Ubuntu does not have installed Curl so we need to install it:

sudo apt-get install curl

Install KVM and perform upgrade:

curl -sSL https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.sh | sh && source ~/.kre/kvm/kvm.sh

kvm upgrade

You can clone now official GitHub repository for ASP.NET vNext using:

git clone https://github.com/aspnet/home

However in order to restore required nuget packages additional certificates installation is required:

CERTMGR=/usr/local/bin/certmgr
sudo $CERTMGR -ssl -m
https://go.microsoft.com
sudo $CERTMGR -ssl -m https://nugetgallery.blob.core.windows.net
sudo $CERTMGR -ssl -m https://nuget.org
mozroots –import –sync

Now you can call in selected project folder following command:

kpm restore

Everything should work for console application, however in order run e.g. MVC project additional configuration is needed (installation of Kestrel from source code):

sudo apt-get -qqy install \
autoconf \
automake \
build-essential \
libtool

In separate folder clone libuv repository:

git clone https://github.com/libuv/libuv

Install and configure it:

./autogen.sh && ./configure && sudo make install
sudo ldconfig

Now for MVC project after calling “kpm restore” you can now run it using:

k kestrel

Transakcje ADO.NET cz. 2

 

W poprzednim poście przybliżyłem nieco ideę zamieszczania w kodzie .NET transakcji. W tej odsłonie postaram się skupić na zagadnieniach nieco bardziej praktycznych. Z góry zapowiadam, że ze względu na ilość materiału ukaże się co najmniej jeszcze jedna odsłona. Jeśli chodzi o transakcje w ADO.NET, uwagę należy tutaj skupić na klasie SqlTransaction. Transakcję ropoczynamy wywołując na obiekcie SqlConnection metodę BeginTransaction(). W omawianym przeze mnie najprostszym przypadku wykorzystywany będzie konstruktor domyślny, aczkolwiek istnieją jeszcze trzy inne – oczekujący nazwy transakcji, bądź też podania poziomu izolacji oraz jednocześnie obu tych parametrów. Obiekt SqlConnection, jak dobrze wiemy, służy do otwarcia połączenia, jeśli oczywiście przekazany został uprzednio connection string do bazy. Po otwarciu transakcji, możemy ją, albo zatwierdzić (commit), albo wycofać (rollback). Szkic takiego wywołania można zatem przedstawić następująco:

SqlConnection connection = new SqlConnection("myConnectionString");
SqlTransaction transaction;

connection.Open();
transaction = connection.BeginTransaction();

try
{
	// Czynnosci zwiazane z obsluga bazy danych
	// .....

	transaction.Commit();
}
catch
{
	transaction.Rollback();
	throw;
}
finally
{
	connection.Close();
}

Łatwo zauważyć, że przy takim podejściu nie ma chociażby obsługi błędów dla wywołania connection.Open(). Nie jest to jedyna wada. Szczególnie należy zwrócić uwagę na to, że transakcję można rozpocząć dopiero po otwarciu połączenia do bazy, czyli właśnie wywołania metody Open(). Odnośnie powyższego kodu, dla porządku parę słów wyjaśnienia – udane wykonanie sekwencji operacji w bloku try{} zatwierdzamy, jeśli zostanie przechwycony jakiś wyjątek w bloku catch{} cofamy transakcję, natomiast w bloku finally{} zamykamy połączenie do bazy, żeby nie zostawiać niepotrzebnie otwartych połączeń.

W podanym powyżej szkicu jest jednak jedna pułapka – nadal transakcją obejmujemy jedną metodę dostępu do danych, Odwołując się do wcześniejszego posta mielibyśmy taką sytuację:

public void CreateUser(...)
{
	// Poczatek transakcji 

	// ---------------------------

	// Ok
	// Wstawienie do tabeli tUsers

	// Źle !
	// Wstawienie do tabeli tTokensHistory

	// --------------------------

	// Koniec transakcji
}

Pisząc taki kod złamalibyśmy oczywiście zasadę, że jedna metoda powinna w zasadzie wykonywać jedną atomową operację, co doprowadziłoby do zaciemnienia kodu. 

Sytuacja do której, według założeń, dążymy to “wyniesienie” transakcji do wyżej położonej warstwy aplikacji. Nazywając warstwę dostępu do danych (zawierającą metody odwołujące się do bazy danych) warstwą DAL (Data Access Layer), tworzymy jednocześnie warstwę BLL (Business Logic Layer), która będzie grupowała pewne jednostki biznesowe realizujące logikę związaną z wstawieniem danych do bazy. Obrazując to na przykładzie, uzyskamy taką sytuację:

// Przyklad niepelny
public class UsersBll
    {
        UsersDAL _users;
        
        public UsersBll()
        {
			// Celowo wykasowana linia inicjalizujaca obiekt transaction...
            _users = new UsersDAL(transaction);
        }

        /// <summary>
        /// Creates user in proper tables in db
        /// </summary>
        public void CreateUser(UserModelExt user)
        {
            try
            {
                transaction.BeginTransaction();
                
                // Set of operations
                int? userId = _users.CreateUser(user);

                // Create token in tokens history table
                if (userId.HasValue)
                    _users.CreateTokenInHistory(userId.Value, Guid.NewGuid().ToString());
                else
                    throw new ArgumentNullException("UserId was null when trying to create token history entry");

                transaction.Commit();
            }
            catch
            {
                transaction.RollBack();
                throw;
            }
        }
    }

Przykład, jak to zostało napisane w komentarzu, jest niepełny, ponadto proszę nie sugerować się nazwą klasy Transaction (to nie jest wspomniana wcześniej klasa SqlTransaction), która została, pewnie dość niezgrabnie, zaimplementowana na moje potrzeby. 

W przykładzie powyższym otwieramy transakcję, wykonujemy ciąg operacji związanych wstawieniem użytkownika do bazy, czyli wstawienie do tabeli tUsers, następnie do tTokensHistory, a na koniec zamykamy transakcję, albo ją commit-ując, albo rollback-ując. Metoda CreateUser(…) umieszczona w warstwie BLL tym samym realizuje kilka operacji, z których jednak każda jest atomowa. Takie podejście jest jak najbardziej tym razem pożądane. W kolejnej odsłonie postaram się zaprezentować w jaki sposób zaimplementować klasę Transaction, aby wszystko ze sobą współgrało (jasne powinno być w tym momencie, że metody w warstwie DAL nie mogą już same ani tworzyć transakcji, ani zajmować się otwieraniem i zamykaniem połączenia – stąd właśnie wynika trudność w zaimplementowaniu takiego rozwiązania).

Transakcje w ADO.NET cz. 1 (wstęp)

 

W nawiązaniu do mojego poprzedniego wpisu na blogu muszę niestety zlożyć małe sprostowanie. Tak zachwalałem zalety umieszczania serwisu na serwerze IIS, że uciekło mi to, że niestety z pomocą Visual Web Developer 2010 Express nie jest możliwe w tym przypadku debugowanie kodu. Wersja ta nie posiada bowiem bardzo ważnej opcji, jaką jest “Atach to process…”. Być może debugowanie z użyciem IIS tym razem w wersji Express wraz z nowościami SP1 do Visual Studio 2010 jest możliwe, jednak nie miałem się okazji z tym tematem jeszcze zapoznać, zatem zostawiam to zagadnienie na inny wpis.

Przechodząc do właściwej części postu, dzisiejszym (oraz pewnie kilku kolejnych postów ze względu na ilość wiedzy do przekazania) tematem będą transakcje w ADO.NET. Po co nam transakcje w aplikacji ? Otóż, na przykład, proces rejestracji nowego użytkownika w serwisie w tworzonej przeze mnie aplikacji opiera się o wstawienie danych do dwóch tabelek. Pierwsza z nich przechowuje dane użytkownika takie jak hasło czy e-mail, druga natomiast tworzy dla niego unikalny token, który zostanie wysłany użytkownikowi na podany przy rejestracji adres e-mail. Użytkownik w celu uzyskania dostępu do pewnych stron będzie musiał potwierdzić swoją rejestrację klikając w otrzymany link rejestracyjny z tokenem. Informacji o przyznanym tokenie nie przechowuję w tabeli użytkownika, gdyż być może okaże się, że token trzeba będzie zmienić, a jednocześnie przy tym zawsze dobrze znać historię przyzwanych tokenów (chociażby po to, aby wiedzieć kiedy użytkownik próbował się potwierdzić). Jednym słowem dane są w dwóch tabelkach dlatego, że jeden użytkownik może mieć przypisany do swojego konta więcej niż jeden token. Wszystko tutaj zależy od wymagań aplikacji tak więc nie da się podać jednej dobrej praktyki. Dla porządku zobaczmy jak wygląda to na wycinku diagramu z bazy danych:

diagram bazy danych uzytkownikow 

Przy tworzeniu nowego użytkownika chcemy uniknąć niespójności danych. Z racji tego, że dane wstawiane będą do dwóch oddzielnych tabelek może się tak zdarzyć, że po wstawieniu rekordu to tabeli tUsers wystąpi jakiś błąd (np. zerwanie połączenia) i pomimo tego, że dane powinny być wstawione również do tabeli tTokensHistory, nie odnajdziemy ich tam w takim przypadku. Doprowadzi to do sytuacji, że użytkownikowi nie zostanie przypisany token, w związku z czym nie będzie mógł on potwierdzić swojej rejestracji. Operacja utworzenia nowego użytkownika powinna zatem być zamknięta w transakcji. Transakcja wymusza, aby wszystkie operacje pomiędzy czasem jej rozpoczęcia i zakończenia zakończyły się sukcesem, lub żadna z nich nie powinna zostać zatwierdzona, czyli wszystkie operacje zostaną anulowane i żadne częściowe zmiany nie zostaną zapisane.

Oczywiście można utworzyć procedurę składowaną, która będzie realizowała operacje wstawienia danych do obu tabel i zamykała je w transakcji. Osobiście preferuję jednak innne podejście, polegające na zachowaniu jak największej atomowości przy wszystkich operacjach. Co jeśli bowiem okaże się, że konieczne okaże się wstawienie danych do jeszcze jednej tabeli albo kilku kolejnych ? Programista niekiedy nie musi być obeznany z tajnikami specyficznej bazy danych, a być może nie ma w pobliżu osoby potrafiącej daną zmianę przeprowadzić. “Wynieśmy” zatem transakcję o poziom wyżej (na co pozwala technologia ADO.NET). Niech pierwsza procedura umożliwia wstawienie danych to tabeli tUsers, a druga do tabeli tTokensHistory, a transakcja w której zostaną one wywołane znajdzie się nie tylko w aplikacji, ale dodatkowo nie w warstwie dostępu do danych, a w warstwie logiki biznesowej. Tym samym obowiązek utworzenia transakcji przechodzi na programistę. Preferuję takie podejście bowiem wyklikanie transakcji w VS z Intellisense jest niczym w porównaniu np. do czasu w jakim otwiera się Management Studio, nie mówiąc już o czasie update’u tam procedury.

Aplikacja na lokalnym IIS 7

 

Swoją aplikację możemy oglądać i debugować na serwerze IIS, który jest dostarczany razem z Visual Studio. Takie rozwiązanie nie jest jednak najlepsze przynajmniej z jednego powodu. Tracimy wtedy możliwość łatwego oglądania aplikacji w różnych przeglądarkach. Oczywiście można ustawić domyślną przeglądarkę, w której otwierana będzie aplikacja. Można również kopiować adres wyrzucany przez Visual Studio do innych przeglądarek, jednak istnieje o wiele prostsze rozwiązanie. Jedyną trudnością jest skonfigurowanie IIS 7 (w przypadku Windows Home Premium) – co pokażę jak zrobić w tym poście.

Samej instalacji IIS nie będę opisywał – taki opis można bez trudu znaleźć w Internecie. Jeśli chodzi o postawienie na nim strony, to tutaj, mimo długich poszukiwań działającego rozwiązania, do dnia dzisiejszego nie udało mi się odnaleźć. Śpieszę zatem podzielić się zdobytą przez siebie wiedzą (opis będzie dotyczył tylko użytku domowego). Zatem do dzieła.

Po stworzeniu aplikacji i jej zbuildowaniu należy uruchomić zainstalowany IIS. Najprościej to zrobić wpisując z paska startu oczywiście komendę IIS. W spisie po lewej stronie na katalogru Witryny klikamy prawym klawiszem myszy i wybieramy opcję “Dodaj witrynę sieci Web”. Po wybraniu tej opcji pokazuję się ekran konfiguracyjny:

iis 7 configuration

W polu tekstowym “Ścieżka fizyczna:” podajemy ścieżkę do katalogu głównego aplikacji, czyli tego, w którym znajduję się chociażby plik default.aspx. Po dodaniu strony przechodzimy do pozycji “Ustawienia zaawansowane…”. Tam należy zmienić pulę aplikacji na DefaultAppPool, co zostało wyróżnione podświetleniem.

iis pool application

Po zaakceptowaniu zmian wybieramy ponadto z zakładki “Akcje” opcję “Edytuj uprawnienia”. Tam musimy dodać do grupy użytkowników dla tego katalogu użytkownika “Wszyscy”.

Na koniec pozbądźmy się zbędnych wpisów w naszej aplikacji w pliku web.config, jednocześnie tymczasowo odblokowując dostęp do strony głównej bez logowania, co przy autentykacji formsowej sprowadza się do umieszczenie następującego wpisu:

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Forms">
      <forms defaultUrl="default.aspx" loginUrl="~/Account/login.aspx" />
    </authentication>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>

Od tej pory wpisująć w dowolnej przeglądarce http://localhost dostajemy się na stronę default.aspx.

ShoppingApp2 – powrót do projektu

 

Czas powrócić, po krótkiej przerwie, do pisania projektu, który z założenia miał być projektem konkursowym. Niestety w tamtym czasie nie udało się go zrealizować, natomiast praca nad jego tworzenie pozwoliła mi na poznanie podstaw ASP.NET. Połączone z tym pomysłem blogowanie było jednocześnie moją pierwszą próbą do przelania swoich zmagań z nauką “na papier”. Zainteresowanie tak początkującym podejściem przeszło moje najśmielsze oczekiwania (potęga sieci). Mając już odrobinę usystematyzowaną wiedzę chciałbym powrócić do tego pomysłu. Mam nadzieje, że i tym razem uda mi się przekazać nieco swojej skromnej wiedzy Winking smile

Pierwszą zmianą przed dalszą pracą jest zmiana nazwy projektu (tamten zostawmy w spokoju Smile ). Od teraz moje nowe linie kodu trafiać będą do projektu http://shoppingapp2 .codeplex.com. Nie zmienia się technologia oraz narzędzia, czyli w dalszym ciągu będzie to Microsoft Visual Web Developer 2010 Express (ze wszystkimi tego konsekwencjami). O założeniu konta na Codeplexie oraz używaniu Mercuriala i klienta TortoiseHg już kiedyś pisałem, zatem nie będę powracał do tego tematu. Zainteresowanych odsyłam do przejrzenia archiwalnych postów oraz pod ten link http://tekpub.com/codeplex. Jako, że moje produkcyjne środowisku już od pewnego czasu istnieje i przeżyło dużo zmian, więc tym razem niestety część z przedstawianych przeze mnie czynności może nie wyglądać dokładnie tak jak w przypadku czystego środowiska. Dla osób zaczynających pracę z tą wersją Visual Studio pierwsza wskazówka na początek. Zacznijmy od przestawienia trybu  ustawień na expert settings:

VisualStudio expert settings

Ciąg dalszy już wkrótce….