niedziela, 1 marca 2009

Firebug console.

firebug Jeśli jesteś programistą Web, to na pewno znasz dodatek do przeglądarki Firefox, a mianowicie Firebug. Jeśli go nie znasz, to MUSISZ go poznać. On powie Ci wszystko o tym co się dzieje z Twoją stroną.

Nie będę się skupiał na tworzeniu instrukcji obsługi tego dodatku, a skupię się na jego jednym z głównych elementów, czyli konsoli. Mam tutaj na myśli obiekt console, ktory jest globalnie dostępny na Twojej stronie dzięki Firebugowi, a być może do tej pory nie zdawałeś sobie sprawy o jego istnieniu.

Obiekt console jest typowym loggerem komunikatów, które służą w celach (głównie) debugowania aplikacji (więcej o logowaniu zdarzeń można przeczytać na moich poprzednich notkach). Wartości do niego przekazywane są widoczne bezpośrednio w okienku Fiebuga. Aby z niego skorzystać, wystarczy wywołać odpowiednią metodę. Jako parametry możemy przekazać dowolną liczbę obiektów (nazw zmiennych) oddzielonych przecinkiem.

console.log Wypisuje komunikat na konsoli Firebuga
console.debug Wypisuje komunikat wraz z linkiem do bloku kodu, który go wywołał
console.info, console.warn, console.error j.w. wraz z graficzną informacją typu komunikatu
console.trace Wypisuje stack trace wywołania kodu JavaScript. Wyświetla wartości parametrów funkcji.
console.assert Testuje czy podane jako argument wyrażenie logiczne jest prawdą
console.dir Wyświetla właściwości danego obiektu

Formatowanie komunikatów:

%s Jako ciąg znaków
%d, %i Jako liczba całkowita
%f Jako liczba zmiennoprzecinkowa
%o Odnośnik do obiektu

 

Przykład wywołania (kod javascript):

console.log("Zmienna: %s zawiera liczbę: %d", mojaZmienna, count);

console.log("Zmienna %s oraz wiele wartości:", mojaZmienna, war1, war2, war3);


Przykładowy efekt działania konsoli Firebuga:



screen_01 2009.03.01 21.21



Możliwości tego narzędzia są bardzo duże. Zdecydowanie jeden z moich ulubionych dodatków do FF. Pozdrawiam.

piątek, 27 lutego 2009

IoC oraz ASP .NET MVC

logo W tej notce postaram się przedstawić rozwiązanie pewnego częstego problemu z jakim spotykamy się podczas tworzenia aplikacji w modelu MVC.

Zapewne rzadko kiedy kontroler może obyć się bez dostarczenia mu obiektu reprezentującego repozytorium danych. Nieważne, czy jest to lista użytkowników, produktów, czy inna podobna inna lista, operacje na niej (choćby wyświetlanie danych) są wykonywane przez logikę biznesową zawartą właśnie w kontrolerze. Przyjmijmy, że chcielibyśmy zasilić nasz HomeController właśnie obiektem reprezentującym listę produktów. Jak tego dokonać? Jest kilka sposobów. Pierwszym z nich jest utworzenie własnego ControllerFactory. Jednak w naszym przypadku oprogramowanie zajęło by za dużo czasu :-)

Z pomocą przychodzi nam mechanizm IoC, który świetnie nadaje się do naszego MVC-problemu. Nie będę zajmował się tutaj wyjaśnianiem samego mechanizmu inversion of control, gdyż zakładam, że czytający ten tekst ma przynajmniej podstawowe pojęcie w tej dziedzinie. Ja wykorzystam do tego celu kontener Ninject.

Strategy pattern Zanim zaczniemy co kolwiek kodować warto rozejrzeć się "po okolicy" i zaplanować najlepszy sposób rozwiązania naszego problemu.

public class TestController : Controller 
{
  private ClientRepository _clientRepository;
  public TestController() {
    _clientRepository = new ClientRepository();
  }
  public void Add(string clientName) {
    _clientRepository.InsertNewClient(clientName);
  }
}


Powyższy fragment kodu (który na razie traktujmy jako pewien pseudokod) wydaje się być w miarę dobrym podejściem do utworzenia naszego repozytorium klientów. Podczas tworzenia kontrolera w jego konstruktorze powołujemy do życia obiekt typu ClientRepository i przechowujemy w prywatnej zmiennej.

Wady! Zdecydowaną wadą tego rozwiązania jest właśnie zależność. TestController ma zależność co do ClientRepository. Nie jesteśmy w stanie przekazać do naszej zmiennej repozytorium _clientRepository innego typu repozytorium, nawet gdyby ich kontrakt był taki sam (w przypadku repozytoriów często przecież tak jest) - bez zmiany kodu konstruktora: tightly coupled (ps. jak to przetłumaczyć? :-) ).


I dopiero po tak przydługim wstępie na scenę wchodzi StrategyPattern (w wolnym tłumaczeniu: wzorzec strategii).



strategy_simple 
Refaktoryzujemy nasz kod. Czas, aby wykorzystać wspomnianą bibliotekę Ninject.



Chcemy użyć mechanizmu wstrzykiwania przez konstruktor (oczywiście nic nie stoi na przeszkodzie aby zrobić to przez właściwość, czy metodę - jednak to już każdy w domu może sobie zrobić :-) ). Ninject ma kilka metod, które świetnie działają w połączeniu z kontrolerami. Ale po kolei. Pierwsze co musimy zrobić, to dodać dziedziczenie (w Global.asax) dla klasy MvcApplication z klasy NinjectHttpApplication.



public class MvcApplication : NinjectHttpApplication

Następnie przeciążamy dwie metody: RegisterRoutes oraz CreateKernel. Pierwsza z metod może być implementowana w taki sam sposób jak to było zaimplementowane dotychczas. Ważna jest wspomniana metoda CrateKernel.

protected override IKernel CreateKernel()
{
    IModule[] modules = new IModule[]
    {
 new AutoControllerModule("Testowa.Controllers"),
        new ServiceModule()
    };
    return new StandardKernel(modules);
}

internal class ServiceModule : StandardModule
{
    public override void Load()
    {
        Bind<Testowa.Controllers.IRepository>().To<Testowa.Controllers.ClientRepository>();
    }
}


Czyli po kolei: Tworzymy tablicę modułów (można to zrobić bez tablicy także). Za pomocą AutoControllerModule "przypinamy" się do zewnętrznej biblioteki klas kontrolerów znajdującej się w Testowa.Controllers. Ja preferuję wydzielenie kontrolerów do zewnętrznej biblioteki - jeśli jednak u Ciebie kontrolery znajdują się w tej samej assembly co aplikacja Web, to możesz użyć metody Assembly.GetExecutingAssembly() przekazanej jako parametr do konstruktora AutoControllerModule. Natomiast metoda Load naszego modułu binduje implementację interfejsu IRepository jako obiekt typu ClientRepository wszędzie tam, gdzie będziemy potrzebować typu IRepository.

Konsumpcja

Tworzymy nasz HomeController wiedząc, że wszystkie zależności automagicznie rozwiąże za nas Ninject. W tym celu w naszym przeprostym kontrolerze piszemy coś na wzór:



public class HomeController : Controller
{
    private readonly IRepository _service;
    public HomeController(IRepository clientRepository)
    {
        this._service = clientRepository;
    }
}


Zależności zostały zerwane, obiekty powoływane są do życia "same". Robimy sobie kawę.

poniedziałek, 2 lutego 2009

SharpArchitecture 1.0 Beta i ASP .NET MVC RC1

Ci który zdąrzyli zaktualizować środowisko ASP .NET MVC do wersji RC1 oraz używają SharpArchitecture w wersji 1.0 Beta, mogą być niemile zaskoczeni błędami podczas uruchomienia ich dotychczasowych aplikacji min. HttpUnhandledException.

Niestety SharpArch w wersji 1.0 beta nie współpracuje z wersją RC ASP .NET MVC i w momencie pisania tego artykułu rewizja kodu nr: 346 także nie wprowadzała tego bugfixu. Programiści trochę ociągają się z poprawianiem tego uniedogodnienia. Aby jednak nie rezygnować z projektów pisanych na nowej platformie należy poradzić sobie samemu :-) SharpArchitecture udostępniany jest jako projekt open source dlatego piersze co należy zrobić, to ściągnąć jego kody źródłowe, następnie otwieramy je:

  1. Aktualizujemy biblioteki MVCContrib: ja mam w wersji: 0.0.1.214
  2. Aktualizujemy biblioteki System.Web.Mvc , .Abstractions, .Routing
  3. Modyfikujemy plik WindsorExtensions.cs projektu SharpArch.Web.Castle następująco:
    1. Dodajemy using ControllerDescriptor = MvcContrib.ControllerExtensions;
  4. Modyfikujemy plik AreaViewEngine.cs:
    1. Dodajemy parametr useCache metody FindPartialView następująco: public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
    2. Refaktoryzujemy wszystkie wywołania w/w metody poprzez wprwadzenie parametru useCache
  5. Po przebudowaniu projektu dodajemy nowe pliki dll do naszego dotychczasowego projektu.

Pamiętajcie o przebudowaniu całości po wprowadzeniu zmian!

piątek, 30 stycznia 2009

Po XV spotkaniu PG.NET. Krótka relacja.

Parę słów na temat tego co działo się podczas 15 już spotkania: "Poznańskiej Grupy .NET".

Pierwsza prezentacja dotyczyła narzędzia XPO firmy DevExpress. Prezentacja prócz omówienia w.w. narzędzia była krótkim, ale wyczerpującym omówieniem najpopularniejszych graczy na rynku OR/Mappererów, min. NHibernate i EntityFramework. Samo rozwiązanie DevExpressa zaprezentowało się całkiem nieźle. Widać środki włożone w jego rozwój (wizardy, konfiguratory), których próżo szukać w projektach z którym pracuję w "piaskownicy" u siebie (głównie NHibernate). Ciekawe jest to, że wcześniej jakoś nie wiedziałem o tym rozwiązaniu, mimo że cenię sobie CodeRush-a tej samej firmy. Myślę, że temat OR/Mapperów powinien zostać pociągnięty dalej, gdyż dyskusje na temat wyższości jednych nad drugimi dało się słyszeć praktycznie cały czas :-) Fajnie by było, gdyby każdy przedstawił podejście do tematu (dostępu do bazy danych w ogóle) na własnym przykładzie, przykładzie firmy w której pracuje, podczas kolejnych spotkań PG.NET!

Prezentacja tycząca projektu OSLO także była ciekawa, choć to już była inna para kaloszy, w porówaniu z XPO. Dużo (i długo) się działo na ekranach pokazywanych przez Marcina. Pewnie wiele, jeszcze zostało do pokazania, ale najważniejsze jest to, że każdy mógł zaobaczyć troszkę inne podejście do projektowania systemów. Troszkę... całkiem inne! :-) Mimo, że przed OSLO jeszcze długa droga, to na pewno ten sposób modelowania znajdzie zastosowanie w życiu.

Jak zwykle można było się dowiedzieć wielu fajnych rzeczy i zgarnąć troszkę softu :-) Wieczór jak najbardziej udany!

środa, 28 stycznia 2009

PG.NET: XV Spotkanie, czwartek

W czwartek 29 stycznia o godz. 18:00. Bezpłatna rejestracja i pełna agenda znajduje się TUTAJ

Co na spotkaniu?

  1. Modelowanie rzeczywistości w OSLO by Marcin Kruszyński
  2. eXpress Persistent Objects na tle  innych narzędzi ORM by Michał Korsak

Nie warto tego przegapić! :-)

czwartek, 22 stycznia 2009

ASP .NET MVC & Membership

Wbrew pozorom wykorzystanie mechanizmu Membership And Role Providers na platformie ASP .NET MVC nie jest bardzo trudne.

Ja preferuję wykonanie do tego celu osobnego kontrolera (AccountController) oraz zaimplementowanie w nim metod służących do uwierzytelniania i autoryzacji użytkowników.

Przykładowy kod metody Login:

public ActionResult Login(string username, string password, bool? rememberMe)
        {
            ViewData["Title"] = "Login";
            // Non-POST requests
            if (Request.HttpMethod != "POST")
            {
                return View();
            }
            List<string> errors = new List<string>();
            if (String.IsNullOrEmpty(username))
            {
                errors.Add("You must specify a username.");
            }
            if (errors.Count == 0)
            {
                bool loginSuccessful = Membership.Provider.ValidateUser(username, password);
                if (loginSuccessful)
                {
                    FormsAuthentication.SetAuthCookie(username, rememberMe ?? false);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    errors.Add("The username or password provided is incorrect.");
                }
            }
            ViewData["errors"] = errors;
            ViewData["username"] = username;
            return View();
        }

Pozostałe metody implementujemy analogicznie pamiętając że zapytanie do nich powinno przyść w metodzie typu POST.

wtorek, 13 stycznia 2009

W walce ze spamem, czyli na co szkoda czasu?

Pewnie każdy codziennie dostaje sporą ilość niechcianych wiadomości email. Pewnie wielu wie, że roboty spamowe codziennie przemierzają setki stron internetowych w poszukiwaniu ich pożywienia, czyli adresów email.

No tak, ale my nie chcemy, aby nasz adres padł łupem takiego robota, dlateo zapewne wielu z Was zamiast podawać swój adres email jawnie, podaje go w formie "zaszyfrowanej", czyli np. jkowalski(at)onet.pl, jkowalski(wytnijto)@onet.pl, jkowalski(at)(wytnijto).onet.pl itp. Wariacji tego formatu jest wiele. Fatk: marnujesz swój czas i palce na wklepywanie podobnych utrudniaczy.

Postanowiłem wykonać pewien eksperyment. Założyłem nową skrzynkę na prywatnym serwerze, zarejestrowałem się na kilku forach (polskich i zagranicznych), a wszędzie gdzie podawałem mój email, stosowałem w/w zakodowaną formę zapisu. Umieściłem także emaile w takiej formie na paru "zwykłych" stronach internetowych. Wszystko by nakrmić roboty. Efekt: w ciągu 2 tygodni otrzymałem na każdą ze krzynek po ok 40 niechcianych wiadomości (viagra, ulepszacze męskich części ciała :-) itp, itd).

W sumie efekt był łatwy do przewidzenia, mimo że wielu pewnie wieży w skuteczność opisywanej metody. A czy istnieje pewna forma ochrony przed spamem przy jednoczesnym podaniu swojego maila? Jak narazie znam jedną: umieszczanie swojego emaila w postaci obrazka, tylko nie stosujcie przy tym linków mailto bo efekt będzie żaden! Niestety nie zawsze da się ją zastosować i jest dość uciążliwa dla ją stosujących.

 spam3