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ę :)

StackOverflow.com otwarte

Stack Overflow to dzieło dwóch, całkiem znanych w świecie inżynierii oprogramowania osobistości – Jeffa Atwooda i Joela Spolsky’ego. Czym jest Stack Overflow? W skrócie, jest to strona, na której można zadać pytanie dotyczące programowania i otrzymać fachową odpowiedź :) Przynajmniej takie są założenia.

Po zadaniu pytania wszyscy mogą na nie odpowiadać oraz głosować na inne odpowiedzi (zarówno na + jak i na -). Odpowiedź z największą ilością plusów wędruje na samą górę. Proste i mogłoby się zdawać – mądre. Istnieje również system reputacji i odznaczeń, aby wyróżniać użytkowników.

Teraz będzie moja osobista opinia. Myślę, że na mało wyrafinowane pytania łatwo będzie tam dostać odpowiedź, gorzej ze znalezieniem już istniejącego wątku. Istnieje co prawda system tagów i wyszukiwanie, ale to chyba za mało. Jeśli nasz problem będzie krytycznie ważny, to chyba mimo wszystko nie jest to najlepsze miejsce do znalezienia odpowiedzi ;) Choćby dlatego, że nie ma tam możliwości dyskusji, zamieszczania załączników itd… Sam być może skorzystam jeśli moje pytanie będzie szybkie i łatwe do zrozumienia. Póki co, traktuję tę stronę jako zapychacz czasu – tj. wchodzę, gdy mam „międzyczas” i czytuję sobie niektóre pytania korzystając z tagów c#, asp.net, .net. Czasem można dowiedzieć się czegoś ciekawego, albo komuś pomóc :)

Aktualnie na stronie jest bardzo duży ruch. Ludzie pytają o wszystko. Począwszy od bardzo wyspecjalizowanych pytań odnośnie konkretnych funkcji, aż do wypisywania swoich ulubionych książek o programowaniu. Co tu więcej pisać, zachęcam do samodzielnego zapoznania się ze stroną. Poniżej parę linków.

Stack Overflow
Jeff Atwood o Stack Overflow
Joel Spolsky o Stack Overflow
Zabawny blog, krytykujący Stack Overflow i jego autorów :)

UPDATE: Stack Overflow jest napisany w oparciu o ASP.NET MVC :) Miło widzieć tak duży, publiczny projekt oparty na tej technologii.

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ść :)

Post Zine Day 2008!

Wczoraj, po godzinie 17 zakończyła się bardzo przyjemna „mini-konferencja” związana z bloggernią zine.net. Z wielką i niepohamowaną radością podzielę się więc swoimi odczuciami i wrażeniami z imprezy :)

Na sali od początku było zdaje się około 50 osób (nie byli to sami członkowie WG.net), a wszystko zaczęło się nieco po 9, bardzo krótkim wprowadzeniem. Zaraz po otwarciu zaczęło się wystąpienie Gaela Fraiteura (autora słynnego narzędzia PostSharp) pt. „Adressing non-functional requirements with aspects”, które świetnie wprowadzało do „filozofii” AOP. Wystąpienie było bardzo zrozumiałe, a szczególnie podobało mi się to, że Gael przedstawił różne frameworki i nie promował tu zbyt szczególnie wspomnianego PostSharpa :) Ponadto warto dodać, że prelekcja była dosyć zabawna, co musiało, nawet najbardziej marudnych, uchronić przed nudzeniem się.

Drugą sesję prowadził András Belokosztolszki – „Managing change in the database world”. Jako dotnetowiec nie spodziewałem się czegoś ciekawego, ale jednak się udało mnie zaskoczyć :) Wystąpienie było również ciekawe i mimo, iż niezupełnie dotyczyło moich zainteresowań, to dowiedziałem się wielu ciekawych rzeczy.

Ostatnia prelekcja tego dnia należała do Gaela Fraiteura i Kuby Binkowskiego „More complex aspects using PostSharp”, która dotyczyła… PostSharpa :) Prowadzona była w bardzo ciekawy – fajny sposób – na zasadzie dialogu pomiędzy „biednym programistą” (Kuba), a „AOP guru” (Gael). Chłopaki pokazali naprawdę dużo interesujących „ficzerów” PostSharpa. Po tej sesji zdecydowanie zainteresowałem się tym narzędziem.

Zaraz po sesji, a właściwie już w trakcie pytań dotarła pizza – rozpoczął się networking :) Tą część wszyscy uwielbiali :) Pizzy i napitku było aż nadto (chyba wszyscy zapełnili żołądki po brzegi :)), ale rozmowom nie było końca. Miło było pogadać dłuższą chwilę w małym kółeczku zainteresowanych z Gaelem (András niestety musiał już uciec). Niestety wszystko co dobre ma kiedyś koniec… A więc po jakichś 45 minutach wszyscy (pozostali na spotkaniu) zostali zaproszeni na rozstrzygnięcie konkursu.

Jaki konkurs? Otóż jakiś czas temu Michał Grzegorzewski zorganizował konkurs na najlepszy, polski, dotnetowy program open source. Uważam, że to był świetny pomysł. Mało w Polsce takich inicjatyw i ciężko coś rozkręcić, a taka inicjatywa jak ta świetnie wspomaga dalszy rozwój. Nie wiedziałem w sumie czego spodziewać się po projektach, które zostaną przedstawione. Myślałem trochę, że może będzie nudnawo, ale… Niech żałują wszyscy, którzy wcześniej poszli sobie z Zine Day! Konkursowa część spotkania była świetna, zaryzykowałbym może nawet, że najciekawsza ;) Zaprezentowano 6 projektów. Wszystkie były bardzo różne, wszystkie były ciekawe! Mówię to z pełną powagą i bez kokieterii. Uczestnicy wykazali się naprawdę dobrymi umiejętnościami przemawiania i promowania siebie :) Gratuluję wszystkim bardzo serdecznie i stanowczo stwierdzam, że wszyscy w tym konkursie zwyciężyli, gdyż naprawdę się popisali!

To były ochy i achy, teraz jedna mała rzecz, która mogłaby zostać zorganizowana lepiej… Otóż, skoro było to Zine Day, to wg mnie było za mało Zina w Zine Day. Wydaje mi się, że dosyć mało osób związanych z Zinem przybyło (choć w sumie, może naprawdę nie mogli). Ponadto zabrakło mi czegoś o samym Zinie. To pierwszy Zine Day, więc można by było przedstawić jakoś krótko historię Zina, jego ewolucję itp. Fajnie, gdyby blogerzy piszący na Zinie powiedzieli coś o sobie lub mieli jakieś krótkie prelekcje na dowolny temat. Tak żeby lepiej poznać osoby, których wypociny czytam na co dzień. Słowem – żeby Zine się trochę promował na takim spotkaniu :) Dwuzdaniowe wprowadzenie, to zdecydowanie za mało!

To jednak zdecydowanie nie może rzutować na mojej opinii na temat Zine Day 2008. Spotkanie było naprawdę świetne – doskonale zrealizowane, zaplanowane, piekielnie ciekawe i niezwykle edukacyjne. Dziękuję Michałowi i wszystkim innym „Zinowcom” za inicjatywę i perfekcyjną realizację! Z niecierpliwością czekam na Zine Day 2009 ;)

PS. Z tego co wiem, będzie dostępny filmik z całej imprezy, gorąco zachęcam do obejrzenia, szczególnie części konkursowej.