35. spotkanie WG.NET

35. spotkanie WG.NET było prawdziwą plejadą gwiazd Zine.net! Kto nie był, zdecydowanie ma czego żałować!

Tradycyjnie odbyły się dwie sesje + przerwa na pogaduchy, czyli networking.

Pierwsza sesję poprowadził Bartek Szafko bardzo aktywny redaktor zina oraz działacz PG.NET opowiadał on o bardzo interesującym i jak się okazało – rozbudowanym instalatorze WIX. Bartek przedstawił podstawy używania tego narzędzia oraz inne dostępne sposoby na „zmajstrowanie” instalatora. Bartek jako naprawdę wprawny mówca świetnie z sesją sobie poradził i zainteresował publikę Windows Installer XML. Z całą pewnością w poważniejszych projektach wykorzystam to narzędzie :)

Po prelekcji przyszła pora na przerwę – socjalizację. Cóż mówić – jak zwykle bardzo miło, jak zwykle bardzo owocnie. Gdy pozna się już kilka osób, te czterdzieści kilka minut można spędzić na bardzo fajnej wymianie zdań.

Po przerwie „na arenę” weszła sława równie wielkiego formatu co Bartek, a mianowicie Maciej Aniserowicz – mistrz pióra Zine.net :) Była to debiutancka prelekcja Maćka i trzeba przyznać, że szykuje się na prawdziwą prelekcyjną gwiazdę :) Maciek opowiedział o Web Client Software Factory. Zagadnienie zdecydowanie bardzo interesujące, a do tego jeszcze bardzo dobrze przedstawione. Mało materiału na „sucho”, a dużo kodu – mniam! To wszystko jeszcze okraszone oryginalnym humorem Maćka :) Sumarycznie – bardzo fajna prelekcja, której naprawdę przyjemnie się słuchało. Ciekawy, życiowy temat i do tego dobrze zaprezentowany.

To tyle o 35. spotkaniu WG.NET. Tradycyjnie na koniec trochę ponarzekam – otóż bardzo przepraszam wszystkich czytelników mojego bloga za ostatnie notki traktujące tylko o odbytych „iwentach”. Niestety na nic innego, odkrywczego nie mam czasu. Mam jednak nadzieję, że szybko się to zmieni.

33. spotkanie WG.NET

Studia mi nie służą (czy już o tym wspominałem?:)), ale tym razem udało mi się nie opuścić 33. spotkania – i bardzo dobrze! :)

Było to spotkanie łączone razem z PLSSUG także pierwsza sesja była dotnetowa, a druga sikłelowa. Sesję .NET poprowadził prosto z Krakowa – Szymon Kobalczyk! Tematem prezentacji był PRISM znany też jako Composite Application Guidance for WPF. Treść wykładu i sama prelekcja były naprawdę megaciekawe! Szkoda tylko, że równie mega co poziom wystąpienia, było moje pouczelniane zmęczenie (od 6 na nogach…) przez co kompletnie nie mogłem się skoncentrować. Niemniej jednak Szymon bardzo mnie zainteresował i z całą pewnością, gdy już (w końcu!) będę miał czas, zajmę się tym tematem :) Obiema rękami podpisuję się pod stwierdzeniem, że Szymon to mistrz WPF-a :) Po zasadniczej części prezentacji, Szymon pokazał odrobinę „magii”, czyli swego rodzaju implementacje MS Surface (rękawice rządziły :D) :) Ta część była równie wspaniała, co poprzednia i chyba jeszcze bardziej zaskakująca :)

Po bardzo krótkiej przerwie, przyszła pora na prezentację SQL-ową. Niestety temat tej prelekcji był (jak dla mnie – bazodanowego laika) bardzo zaawansowany i niewiele z tego wystąpienia wyniosłem – ot ogólne pojęcie czym tytułowy Service Broker (bo o nim była mowa) jest. Nie podejmuję się więc oceny tego wystąpienia. Wydaje mi się tylko, że Krzysztof Bąk – główny prelegent przesadził trochę z ilością materiału, który chciał zaprezentować. Wierzę jednak, że skoro w przygotowaniu brał udział Paweł Potasiński to musiała być ona dla SQL-owców smacznym kąskiem :)

Tyle mojej relacji, a teraz idę odpoczywać (ach, strasznie marudny się zrobiłem przez te studia! :)).

Przygarnij mnie – szukam drużyny na Imagine Cup :)

Początki studiowania zajmują mi masę czasu, tym niemniej chciałbym zrealizować swoje mini-marzenie i wystartować w Imagine Cupie :) Najbardziej zainteresowany jestem kategorią Software Design, ale jestem otwarty na wszystkie inne kategorie programistyczne. Jeśli więc do Twojego teamu brakuje osoby to polecam się poprzez dział kontakt. Nie jestem nastawiony na wielki sukces, a jedynie na przednią zabawę :)

31. spotkanie WG.NET

26 września, tradycyjnie o godzinie 18.00 rozpoczęło się 31. spotkanie WG.NET. Także i tym razem było niezwykle miło i ciekawie :)

Pierwsze wystąpienie należało do Kuby Binkowskiego i było rozwinięciem tematu zaczętego na Zine Day, a mianowicie dotyczyło AOP i DI – „AOP i DI wg P&P, czyli Unity i Policy Injection Application Block”. Tak jak w tytule Kuba opowiadał o dwóch frameworkach – PIAB i Unity. Temat jest niebanalny, więc wykład wymagał dużo skupienia. Nasz prelegent jednak się spisał i przedstawił temat bardzo zgrabnie. PIAB przedstawione było na bazie (powiedzmy :P) biznesowej aplikacji, natomiast Unity zdominowane było przez kulinarne skojarzenia, za co należy się Kubie lincz (18.00 to jak słusznie zauważył zdaje się Kuba Gutkowski pora kolacyjna!) :) Wyczerpanie tematu w godzinnym wykładzie jest niemożliwe, jednak wydaje mi się, że możliwości i filozofie obu frameworków zostały bardzo dobrze zaakcentowane. Brawo Kuba! :)

Po pierwszym wystąpieniu, tradycyjnie już była krótka przerwa na pogadanki. Jak zwykle można było ją spędzić bardzo miło. Wydaje mi się, że pomysł z przerwami na networking się przyjął i jest naprawdę doskonały!

„Praktyczny przegląd możliwości TFS 2008” – tak brzmi tytuł drugiego wykładu przeprowadzonego przez Marka Byszewskiego. Znów temat bardzo obszerny ale i bardzo ciekawy. Mam wrażenie, że bardzo zainteresował całą publikę :) Prezentacja była bardzo rzeczowa i zawierała praktyczne same przykłady i pokazy – czyli to co programiści lubią najbardziej :) Mam nadzieję, że temat będzie jeszcze rozwijany! Gratulacje za świetną prelekcję! Osobiście lubię ten bardzo spokojny styl, w którym Marek prowadzi wystąpienia :)

Tyle z 31. spotkania. Żal tylko, że następne, 32. spotkanie WG.NET prawdopodobnie dopiero za miesiąc!

ASP.NET MVC – autoryzacja użytkowników dla leniwych

Jeśli chcemy ograniczyć użytkownikom dostęp do różnych funkcjonalności naszej strony napisanej w ASP.NET MVC możemy skorzystać z przydatnych Membership Providerów (tak jak w przykładowej aplikacji MVC), możemy też zainteresować się czymś takim. Również kuszącą opcją jest skorzystanie z (mniej lub bardziej rozbudowanej) Forms Authentication znanej dobrze z „czystego” ASP.NET. Ja skusiłem się na tę ostatnią opcję, gdyż chciałem uzyskać efekt minimalnym nakładem pracy.

Jeśli prowadzicie blog, jedyne czego Wam potrzeba, to ograniczyć „anonimowym” dostęp do pewnych stron i akcji (jak np. dodawanie nowych notek), a dla siebie zatrzymać pełne uprawnienia. W tej sytuacji moje minimalistyczne rozwiązanie wydaje się być rozsądne :) Do rzeczy!

Na początek, w głównym pliku Web.config naszej aplikacji musimy dodać:

<authentication mode=”Forms />”

Aby nasza aplikacja wiedziała, czego od niej chcemy ;) Teraz należałoby stworzyć zwykły widok-formularz, w którym umieścimy pola login i hasło oraz odwołanie do odpowiedniej akcji, na przykład:

<form action=”/Admin/Authenticate/” method=”post”>

To znaczy, że po wciśnięciu przycisku submit uruchomiona zostanie akcja podłączona pod route (to wszystko można ustawić w Global.asax) „http://naszaplikacja.com/Admin/Authenticate/” przekazując przy tym wartości pól Login i Password. Proste, prawda? Teraz należałoby obsłużyć żądanie w kontrolerze. Przykładowa akcja poniżej:

[AcceptVerbs("POST")]
public ActionResult Authenticate(string Login, string Password)
{
if (!ZaawansowaMetodaAutoryzacji())
throw new Exception();
else
{
FormsAuthentication.SetAuthCookie("Admin", false);
return Index();
}
}

Bardzo ważna jest tutaj linia:

FormsAuthentication.SetAuthCookie(„Admin”, false);

To ona spowoduje, że zostaniemy autoryzowani jako użytkownik „Admin”. Drugi parametr („false”) działa jak znane pole „Remember me”, więcej do poczytania tutaj. Fajnie, prawda?

Teraz pozostaje nam już tylko oznaczyć odpowiednie akcje jako chronione. To ważne, chrońcie akcje a nie strony! Odpowiedź czemu zdaje się być oczywista. W dobrze napisanej aplikacji MVC każdy widok (każda strona) renderowana jest po przejściu przez kontroler, a więc przez odpowiednią akcję. Jeśli zabronimy „anonimowym” dostępu do odpowiednich akcji uzyskamy niemal 100% pewność, że nie obejrzą oni danej strony, ani nie wywołają nieprzeznaczonej dla nich metody (np. tworzącej nowy wpis na blogu) :) Jak zabronić dostępu użykownikowi do danej metody (akcji)? To bardzo proste. Wystarczy metodę oznaczyć atrybutem PrincipalPermission. Na przykład:

[PrincipalPermission(SecurityAction.Demand, Name = "Admin")]
[AcceptVerbs("POST")]
public RedirectToRouteResult AddEntry(string Title, string Text)
{
dataContext.AddEntry(Title, Text);
return RedirectToAction("Recent", "Blog");
}

Dzięki temu metoda – wpis może być dodany tylko przez użytkownika „Admin”. W taki sposób oznaczamy wszystkie metody, do których chcemy dodać restrykcje. To tyle! Tym sprytnym sposobem nasza aplikacja jest chroniona w bardzo prosty sposób :)

Źródła mojego bloga w końcu dostępne! :)

Po wielu zapowiedziach w końcu są :) Źródła mojego bloga (hLog) dostępne do ściągnięcia w dziale Projekty. Jest to mój pierwszy projekt w ASP.NET MVC i w ogóle w ASP.NET. Jestem więc otwarty na sugestie, propozycje, uwagi i krytykę – w komentarzach bądź via dział Kontakt. Zachęcam do ściągania! :)

PS. Mój feed jest teraz obsługiwany przez FeedBurner. Wszystkich aktualnych subskrybentów prosiłbym o zmianę adresu na http://feeds.feedburner.com/LukaszSowa/ a niesubskrybentów o subskrybcję :)

Transformacje w WPF

W lipcu przyszło mi wykonywać dla pewnej firmy projekt łudząco przypominający zastosowanie Microsoft Surface. W mojej gestii leżało napisać program, który na podstawie przyjmowanych od panelu dotykowego współrzędnych będzie manipulował (transformował) obrazki. Ot, taki terminal, na którym klienci mogą sobie w przyjemny sposób pooglądać zdjęcia produktu. Przy okazji tego projektu zasięgnąłem poważnej lekcji WPF-a i długo zmagałem się z transformacjami graficznych obiektów – dlatego stwierdziłem, że warto napisać o paru aspektach tego zagadnienia :)

Wygodne transformowanie obiektów graficznych w WPF-ie to jedno z dobrodziejstw, które owa technologia oferuje, w szczególności jeśli zestawić ją z WinForms i GDI. Transformować możemy obiekty wszystkich klas, które dziedziczą po UIElement. Każdy taki obiekt posiada 2 właściwości: RenderTransform i LayoutTransform do której przypisujemy naszą transformacje. Czym różnią się te właściwości? Można o tym przeczytać tu albo uruchomić krótkie demo (koniecznie w IE), dostępne tu.

Teraz może nieco o transformacjach. Dostępnych typów transformacji jest cztery:

  1. RotateTransform – obrót o podany kąt (w stopniach) i podany środek obrotu (punkt)
  2. ScaleTransform – skalowanie, w punkcie skalowania, w dwóch płaszczyznach (X i Y) o podanej skali (oddzielnie X i Y); wartości >1 powiększają a wartości należące do przedziału (0;1) pomniejszają
  3. SkewTransform – „skośne” transformowanie o podane kąty (X i Y) oraz środek „skosowania” ;) – służy często do tworzenia iluzji trójwymiarowości
  4. TranslateTransform – najzwyklejsza translacja o wektor – wymagane są dwie współrzędne wektora

Więcej polecam poczytać więcej na MSDN, są nawet ładne rysunki :)

Przechodząc do rzeczy, aplikowanie transformacji jest bajecznie proste. Załózmy iż mamy obiekt typu ImagearrowImage i chcemy go przesunąć o wektor [50,82]. Wystarczy jedynie napisać:

arrowImage.RenderTransform = new TranslateTransform(50,82);

i gotowe :)

W taki sposób możemy jednak dodać tylko jedną transformację. Co jeśli chcemy zaaplikować naszemu obiektowi całą grupę transformacji? Wystarczy wtedy skorzystać z klasy TransformGroup:

TransformGroup transformGroup = new TransformGroup();

i teraz:

transformGroup.Children.Add(rotateTransform);

transformGroup.Children.Add(translateTransform);

transformGroup.Children.Add(scaleTransform);

pozostaje zaaplikować grupę transformacji:

arrowImage.RenderTransform = transformGroup;

tadam! Gotowe :)

Na koniec chciałbym zaznaczyć, że transformacje mają na siebie wpływ np. pomniejszenie obiektu o połowe powoduje iż translacja o wektor [8,0] jest tak naprawdę translacją o wektor [4,0]. Chyba, że zrobimy najpierw translacje, a potem pomniejszanie. Tutaj należy pamiętać, iż dodawanie transformacji nie zawsze jest przemienne: kolejność translacji nie ma znaczenia – wynik zawsze będzie taki sam; co innego np. z obrotem. Dokumentacja niestety nie jest zbyt wyczerpująca w tej kwestii. Osobiście męczyłem się tydzień, żeby zrozumieć cały mechanizm współdziałania między transformacjami – trzeba być naprawdę bardzo uważnym. Dla przykładu – najbardziej „aktualne” (te które mają być zastosowane najpóźniej) transformacje należy wstawiać na początku, a nie na końcu kolekcji.

transformGroup.Children.Add(rotateTransform); transformGroup.Children.Add(translateTransform);

Taki kod spowoduje najpierw translacje, a potem obrót. Jeśli więc chcemy uzyskać efekt wielokrotnej transformacji przydatne staje się coś takiego:

transformGroup.Children.Insert(0, pewnaTransformacja);

To by było na tyle. Jeszcze nie jestem pewien, czy mogę, ale być może wspomniana aplikacja a’la Surface zostanie opublikowana na moim blogu :) Tymczasem polecam spojrzenie na podobną aplikację – napisaną w Silverlighcie. Jej kod źródłowy jest cennym przykładem stosowania transformacji :)

30. spotkanie WG.NET

Wczoraj, to jest 11 września w godzinach 18-21 odbyło się 30. spotkanie WG.NET, połączone z 23. spotkaniem PLSSUG. Jak zwykle było miło, ciekawie i bardzo „edukacyjnie” :)

Po krótkim wstępie, który dotyczył przyszłości (w tym, zapowiedź C2C ’09!) oraz nadchodzącego MTS-a zaczęła się część zasadnicza – prelekcje. Pierwsze wystąpienie przygotowane było przez Łukasza Skrzypczyńskiego i dotyczyło BizTalka. Prezentacja bardzo mi się podobała – interesujące wprowadzenie do tego niezbyt znanego narzędzia. Niewiele suchych faktów, a dużo dem :) Bardzo fajnie było posłuchać Łukasza (jakie to ładne imię :)), mimo iż zapewne BizTalka nigdy używać nie będę :)

W przerwie między wystąpieniami było 35 minut socjalizowania się :) Jak zwykle było bardzo miło i przyjaźnie – szczególnie przyjemnie rozmawiało się z Pawłem Potasińskim o studiach, Oracle’u i Microsofcie. Pozdrawiam :)

Druga prezentacja miała nieco tajemniczy tytuł „Pesymistyczna strategia blokowania danych” i prowadził ją Wojciech Sawicki. Wystąpienie dotyczyło współpracy użytkowników bazy danych – tj. kiedy blokować, a kiedy nie, dane które mogą ulec zmianie. Prelekcja była zabawna, świetnie prowadzona – bardzo mi się podobała, mimo iż była wybitnie SQL-owa :) Temat wzbudzał wiele emocji i jednostronne przemówienie często przeradzało się wręcz w mały panel dyskusyjny – super! :) Gratulacje dla Wojtka! Dodam jeszcze, że w mojej czteromiesięcznej karierze w grupie offline’owej zdarzyło mi się wiele SQL-owych prezentacji i o dziwo, mimo iż jestem bazodanowym „newbie” bardzo dużo (ale nie wszystko :P) z nich zrozumiałem i wyniosłem – także brawo dla prelegentów i PLSSUG za dobór odpowiednich ludzi :)

Po prelekcjach było króciutkie zakończenie i była pora zbierać się do domu. Najbliższe spotkanie mam nadzieje jeszcze we wrześniu. Już nie mogę się doczekać! :)

Tworzymy własny kanał RSS 2.0, czyli kodujemy!

Jeśli prowadzisz stronę z dynamiczną zawartością, to z całą stanowczością potrzebujesz udostępniać ją jako kanał informacyjny. Coraz więcej osób (w tym od niedawna ja ;)) przegląda niusy, wpisy na blogach tylko i wyłącznie używając syndykacji. Ba, myślę nawet, że wiele stron z powodzeniem istniałoby bez jakiegokolwiek layoutu, a jedynie jako feed :) Ale dosyć już spekulacji, do dzieła! :)

Istnieją dwa liczące się standardy kanałów są to Atom i RSS. Polecam zapoznać się z linkami z jakże niezawodnej wikipedii :) W tym miejscu wypadałoby zdecydować się na któryś standard. Ja opiszę przygotowanie feeda w RSS 2.0, ale nic nie stoi na przeszkodzie, żeby zdecydować się na Atom. RSS wydaje mi się nadal być popularniejszym (osobiste odczucie), ale Atom depcze mu po piętach.
Na początek wypadałoby utworzyć stronę o jakiejś wdzięcznej nazwie, np. Feed.aspx. To było proste, teraz jednak przechodzimy w końcu do kodu :) Nie będę się tutaj rozwodził nad specyfikacją gdyż można o niej przeczytać tutaj. Jeśli jesteś leniwy, to wikipedia przedstawia bardzo skrótowy opis i przykład, który jednak nam wystarcza. Oto fragmencik pliku generującego kanał z bloga, którego czytasz:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Feed.aspx.cs" Inherits="hLog.Views.Blog.Feed" %><%Response.ContentType = "application/xml";%><%@ Import Namespace="hLog.Models"%>


Łukasz Sowa - blog programisty .NET
http://lukaszsowa.pl
Feed z najnowszymi notkami
<% foreach(Entry entry in ViewData.Model) { %>

<![CDATA[<% Response.Write(entry.Title); %>]]>
]]>
]]>
]]>

<%} %>


Kod powinien mówić sam za siebie. Są wszystkie wymagane pola , a dodatkowo również , które jest bardzo przydatnym polem. Zwróć uwagę na formatowanie (wymagane pola, kolejność, umiejscowienie), gdyż nawet drobne odstępstwa od reguł mogą powodować poważne błędy. Mój blog, czego tutaj niestety nie widać, pobiera 10 najnowszych postów, a następnie osadza je w znacznikach. Wyjaśnienia wymaga jeszcze tajemnicza CDATA. Otóż podczas parsowania pliku, w wygenerowanej zawartości mogą znaleźć się elementy, które zaburzą układ znaczników, a co za tym idzie – cały nasz Feed wygeneruje się z błędem. Tu właśnie przychodzi z pomocą CDATA. Wszystko co znajduje się pomiędzy znacznikami CDATA jest ignorowane podczas parsowania – czyli nasze dane nie zaburzą znaczników.

No to pozostaje tylko odpalić stronkę i… ups! Kanał wyświetla się zapewne jako plaintext. Nie tego oczekujemy. Podgląd odebranego nagłówka wszystko wyjaśnia – przeglądarka traktuje dane, jako test. Musimy więc odpowiednio oprogramować zdarzenie Page_Load. Kod poniżej:

 protected void Page_Load(object sender, EvenrArgs e)
{
Response.ContentType = "application/xml";
}

Teraz nasza przeglądarka będzie wiedziała (dzięki zmodyfikowanemu nagłówkowi), że odczytuje XML.

Teraz już powinno wszystko działać. Voila! :) Ciesz się swoim własnym kanałem.

PS. To mój pierwszy stricte techniczny tekst, więc liczę na feedback i wyrozumiałość :)

System operacyjny dla .NET-owca

Jakieś pół roku temu, poczułem zew nowych wyzwań i postanowiłem zainstalować Vistę Ultimate. Trzeba iść za duchem zmian, prawda? Ostatnimi czasy powątpiewam jednak, czy była to dobra decyzja.

Mój sprzęt to nie jakaś tam super bestia wśród laptopów. Powiedziałbym, że to raczej „średni średniak”. Na początku używania Visty byłem nieco sceptycznie nastawiony. Z resztą, każdy chyba był po tym co można było przeczytać w internecie zaraz po premierze. Po pewnym czasie jednak przyzwyczaiłem się do nowego wyglądu, sposobu używania, stabilności i szybkości. Wszystko w imię nadążania za „duchem czasu”. Do przeglądania internetu, odbierania poczty i słuchania muzyki w zupełności to wystarczało. Niedawno (w maju) skończyłem matury i wróciłem do bardziej aktywnego programowania w .NET. Wrażenia? Dwie instancje Visual Studio 2008 dobijają mój komputer. Uruchamianie się Development Servera trwa i trwa… Ponadto ostatnio mam do czynienia sporo z komputerem z zainstalowanym Windows XP SP2. Zauważyłem, że system bootuje się na nim około 2 razy szybciej (sprzęt jest 2 razy słabszy), a po chwili od pokazania się ikonek na pulpicie system jest gotowy – u mnie, na Viście, „muli” jeszcze około minuty.
Moje pytania brzmi następująco: co Vista ma takiego, czego nie ma XP, a może przydać się programiście .NET? Czy Vista ma jakiekolwiek przewagi nad XP? A może warto spróbować jeszcze czegoś alternatywnego, np. Windows Server 2008 (kompletnie nie wiem, jak to się spisuje jak desktop..). Zapraszam do wypowiedzi w komentarzach.