środa, 28 października 2015

ckEditor Bootstrap modal - znikający edytor

Przy implementacji pewnej strony miałem następujący scenariusz:
1. Po kliknięci w przycisk uruchamiało się okno modalne boostrap modal
2. Do tego okna był ładowany dynamicznie przez ajax'a partial view, który zawierał ckEditor

Wszystko działało prawie ok. Problem był  następujący. Gdy drugi raz kliknęło się w przycisk i ładował się partial view, ckEditor znikał. rozwiązaniem okazało się być zaimplementowanie następującego kodu w partial view (najpierw szukamy czy istnieje już instancja ckEditor'a i jeśli istnieje niszymy ją, następnie ładujemy podownie ckEditor):

<script type="text/javascript">
    var editor = CKEDITOR.instances.EmailContent;
    if (editor) { editor.destroy(true); }
    CKEDITOR.replace('EmailContent');
</script>

niedziela, 18 stycznia 2015

Why not to move to Microsoft Azure?


Trivia

This article describes the fundamentals and core features of Microsoft Azure, a public cloud operating system. Many of my fellow programmers, who are my acquaintances, have never used any kind of ‘cloud platform’, because they either regard it as unnecessary or hold a false believe that programming on it is difficult. Therefore, I have decided to write this article thanks to which I hope I will be able to encourage some of them to use it, or at least get familiar with it. The aim of this article is to give the readers a foundation for understanding Microsoft Azure and encourage them to try out the public cloud application, even if they have not had any understanding about cloud systems so far.

czwartek, 5 czerwca 2014

Managed code vs unmanaged code

Słyszeliście czasami jak sobie dwóch kolegów programistów gada o kodzie zarządzanym/niezarządzanym, że w jednym to tak to działa a w drugim tak, że tutaj to a tutaj tamto, a wy nie bardzo wiedzieliście o co chodzi? No niby znacie .NET framework, prawda? Z racji serii wpisów traktujących o podstawach .NET framework, t tym poście postaram się przedstawić różnicę między kodem zarządzanym (managed code) a niezarządzanym (unmanaged code) w .NET Framework. A post będzie krótki bo i też w zasadzie nie ma o czym gadać a temat prosty i przyjemny. 

Gdy piszemy aplikację, kompilujemy ją i uruchamiamy, niezależnie od tego czy jest to aplikacja desktopowa, aplikacja internetowa czy jeszcze co tam sobie wymyślimy, zawsze działa ona pod kontrolą CLR (Common Language Runtime) o którym pisałem w poprzednim poście. Jest to mechanizm, który kontroluje naszą aplikację, zarządza garbage collectorem, sprawdza czy kod jest bezpieczny i możliwy do uruchomienia, itd. Zasada jest prosta: każdy kod, którą działa pod kontrolą CLR jest nazywany kodem zarządzanym "managed code". Jeśli piszemy jakikolwiek kod w C# lub VB.NET to zawsze będzie to "managed code", innymi słowy będzie to zawsze kod zarządzany przez CLR. 
Unmanaged code jest z kolei kompilowany bezpośrednio do kodu maszynowego. W .NET Framework kod niezarządzany można tworzyć jedynie przy użyciu Visual C++ (oczywiście można również kompilować do kodu zarządzanego, jeśli chcemy np. aby garbage collector załatwiał za nas sprawy związane z czyszczeniem pamięci po nieużywanych obiektach, czy do weryfikacji kodu). Pomyślmy sobie o aplikacji skype jako o przykładzie "unmanage code" (napisany w C/C++). Skype możemy oczywiście uruchomić z poziomu kodu zarządzanego, np. naszej aplikacji napisanej w WinForms, jednak CLR nie ma żadnej kontroli nad kodem niezarządzanym, a co za tym idzie nie ma żadnej kontroli nad naszą aplikacją Skype. Wyobraźmy sobie teraz, że uruchomiliśmy skype z naszej aplikacji, która po chwili łapie jakiś nieobsłużony wyjątek i się wywala - zostanie ona zamknięta czy zrestartowana czy po prostu wywali się z jakiegoś innego powodu. A co z naszym Skypem? - zostanie nadal uruchomiony, bo CLR nie ma nad nim żadnej kontroli. 

IL, CLR, CTS, CLS - czyli jak działa .NET framework

Czy wiecie jak działa .NET Framework? Czy zastanawialiście się, co powoduje, że kod złożony z liter i cyfr, kod który piszecie zamienia się automagicznie na aplikację widoczną gołym okiem. Często w niektórych pytaniach czy odpowiedziach na StackOverflow widziałem jak specjaliści wspominają o IL, CLR, CTS czy CLS. Ba nawet idąc na rozmowę kwalifikacyjną możesz dostać takie pytanie! Przecież to podstawy .NET framework! Ja sam (co wstyd się przyznać) gdy teraz przypominałem sobie wiedzę na ten temat aby popełnić ten post, dodatkowo dowiedziałem się rzeczy, o których wcześniej nie wiedziałem. Jak to się mówi: "Człowiek uczy się całe życie". Jak napisałem wcześniej, ostatnio postanowiłem to nadrobić! Postaram się wyjaśnić to w niniejszym poście co te skróty użyte w tytule oznaczają.

Aby mieć jasny obraz jak wszystko wygląda, spójrzmy najpierw na poniższy schemat zaczerpnięty z wikipedii:

Common Language Runtime diagram.svg
"Common Language Runtime diagram" autorstwa Leif Arne Storset - Praca własna, based on ASCII diagram found at Wikipedia:en:Common Language Runtime. Licencja CC BY-SA 3.0 na podstawie Wikimedia Commons.

Oraz lekko zmodyfikowana, moja własna wersja tego schematu:



Teraz, postaram się zwięźle opisać to co widać na schemacie powyżej, czyli jak to wszystko działa.
  • piszemy swój kod wykorzystując c# bądź vb.net bądź inny język .NET framework (chociaż niekoniecznie)
  • nasz kod musimy skompilować, więc robi to dla nas kompilator, odpowiedni dla danego języka
  • kompilator tworzy tzw. pośredni kod - common intermediate language (CIL bądź IL). Można go rozumieć jako "pół-skompilowany kod" dlatego, że mimo, iż zawiera już pewne instrukcje to kod jeszcze być skompilowany pod odpowiednia platformę i zoptymalizowany pod odpowiednie CPU podczas uruchamiania zwanego runtime. IL jest bezpośrednio tłumaczony dalej na kod bajtowy.
  • następnie nasz IL trafia do CLR czyli Common Language Runtime. To miejsce jest właściwie sercem całego .NET framework. Po otrzymaniu kodu, IL "wrzuca go" do komponentu zwanego JIT (Just in time compiler), który zamienia kod bajtowy na serię instrukcji dla specyficznej platformy. Następnie takie instrukcje są wykonywane. 
Powyższy opis pokazuje przez jakie poszczególne komponenty należy przejść aby nasz kod źródłowy zamienić na kod natywny. Jednak niektóre komponenty muszą być uszczegółowione. Zatem poniżej jeszcze króciutka wzmianka o niektórych komponentach i ich zadaniach:
Common Language Runtime:

  • wbudowany garbage collector - możemy sobie pomyśleć o nim jak o pewnym wątku chodzącym w tle i sprawdzającym, które obiekty w których obszary pamięci są nieużywane i mogą być usunięte z pamięci.
  • Zamienia kod pośredni na kod natywny
  • wbudowany CAS (Code Access Security) - mechanizm kontroli bezpieczeństwa aplikacji oparty na uprawnieniach kodu
  • CV (Code verification) - sprawdza poprawność kodu, np, czy metoda została wywołana z odpowiednią ilością parametrów

CTS (Common type system)

  • jest standardem, który opisuje jak poszczególne typy danych reprezentowane są w pamięci. dzięki któremu możemy wywoływać odpowiedni kod dowolnego języka .NET framework. Innymi słowy, komponent ten zapewnia, że jeśli mamy pewien typ danych zdefiniowany w 2 różnych językach to po kompilacji ten typ danych będzie rozpoznawany jako wspólny typ, dzięki czemu można łatwo komunikować się między dwoma językami. 
CLS Common Language Specification
  • jest to specyfikacja, która zawiera zbiór pewnych zasad i reguł określających jak kod aplikacji może być zamieniony na kod bytowy. Brzmi tragicznie - ale co to właściwie oznacza w przypadku .NET Framework? Oznacza to, że pisząc nasz kod zgodnie z pewnymi określonymi i konkretnymi zasadami w dowolnym języku, będzie on kompatybilny z .NET Framework. Przykład: C# jest językiem w którym rozróżniana jest wielkość liter, VB.NET jest językiem, w którym wielkość liter nie ma znaczenia. Gdy w C# zadeklarujemy 2 zmienne o takiej samej nazwie ale różniące się wielkością liter, kod skompiluje się - ale będzie niepoprawny dla VB.NET. Jest to przykład tzw. CLS-non-compliant code. 

środa, 21 maja 2014

Klonowanie obiektu - deep cloning

Post ku pamięci. Jak szybko i łatwo wykonać klonowanie całego obiektu (tzw. deep cloning). Możemy użyć takiej funkcji:


public object CloneObject(object o)
{
   Type t = o.GetType();
   PropertyInfo[] properties = t.GetProperties();

   Object p = t.InvokeMember("", System.Reflection.BindingFlags.CreateInstance,
   null, o, null);

   foreach (PropertyInfo pi in properties)
   {
      if (pi.CanWrite)
      {
         pi.SetValue(p, pi.GetValue(o, null), null);
      }
   }

   return p;
}

poniedziałek, 19 maja 2014

Prosty klient do konsumowania serwisu ASP.NET Web Api

Załóżmy, że napisaliśmy serwis, który zwraca nam pewne produkty. Nawigując pod odpowiednie dwa adresy URI pobierzemy odpowiednie zasoby:

  • http://localhost/api/products - lista wszystkich produktów
  • http://localhost/api/product/1 - odpowiedni produkt
Wchodzą pod pierwszy adres dostaniemy listę produktów, np. w takiej postaci:



Wiedząc co zwraca nasz serwis możemy wygenerować sobie klasę "Product", z której będziemy mogli później korzystać:
public class Product
{
   public int Id { get; set; }
   public string Name { get; set; }
   public string Description { get; set; }
   public decimal Price { get; set; }
}
W celu połączenia się z naszym Web API, musimy skorzystać z klasy HttpClient. Nasz cały kod może wyglądać następująco:
Metoda, dzięki której tworzymy sobie połączenie do naszego serwisu REST:
private HttpClient GetClient(string mediaType)
{
   string baseUri = @baseAddress + port;
   HttpClientHandler handler = new HttpClientHandler()
   {
      UseDefaultCredentials = false
   };
   handler.Credentials = new NetworkCredential("username", "password");
   HttpClient httpClient = new HttpClient(handler);
   httpClient.BaseAddress = new Uri(baseUri);
   httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType));
   return httpClient;
}
Metoda dzięki której pobieramy produkt:
private async void Get()
{
   using (var client = GetClient("application/json"))
   {
      HttpResponseMessage response = await client.GetAsync("/api/Products/1");
      if (response.IsSuccessStatusCode)
      {
         Product product = await response.Content.ReadAsAsync();
         //Do something with product
      }
   }
}
Metoda za pomocą której dodajemy nasz produkt:
private async void Post()
{
   using(var client = GetClient("application/json"))
   {
      var message = await client.PosAsJsonAsync("api/products",
      new Product
      { 
         Id=111,
         Name="Product 111 name",
         Description = "Product 111 description",
         Price=222,22
      });
   }
}
Metoda za pomocą której usuwamy nasz produkt:
private void Delete()
{
   using(var client = GetClient("application/json"))
   {
      var message = await Client.DeleteAsync("api/products/1");
   }
}

Należy pamiętać, że metoda "ReadAsAsync" jest metodą rozszerzającą i aby z niej skorzystać należy pobrać następującą bibliotekę z nuget'a: Microsoft.AspNet.WebApi.Client

ASP.NET Web API - basic authentication

Basic authentication (ASP.NET Web API)

Tworzenie serwisu REST z wykorzystaniem ASP.NET Web API jest stosunkowo proste. Gdy nasz serwis jest już wystawiony na świat, prawdopodobnym stanie się fakt odpowiedniego jego zabezpieczenia. Jednym z najprostszych i najbardziej standardowym sposobem jest zabezpieczenie takiego serwisu z wykorzystaniem basic authentication
Basic authentication jest najprostszym i najłatwiejszym mechanizmem autentykacji poprzez zastosowanie pary "username/password" w "plaintext".
Basic authentication działa w następujący sposób:

  1. Jeżeli żądanie "request" wymaga autentykacji, serwer zwraca status code "401" (unauthorized). Odpowiedź taka zawiere "WWW-uthenticate header", które mówi, że serwer wspiera "basic authentication".
  2. Klient wysyła kolejne żądanie ("request") ale tym razem już z odpowiednimi "credentials" umieszczonymi w "WWW-Authenticate header". Charakteryzują je następujące właściwości: 
    1. sformatowane jako string: "name:password"
    2. base64-encoded
    3. brak szyfrowania

Basic authentication wykonywany jest w kontekście pewnej domeny ("realm"). Serwer dodaje nazwę tej domeny do nagłówka WWW-Authenticate header. 
WAŻNE:
  • Ponieważ "credentials", które przesyłane są od klienta na serwer nie są szyfrowane, stosowanie basic authentication jest sensowne i bezpieczne jedynie jeśli komunikacja jest bezpieczna i przebiega przez szyfrowaną wersję protokołu HTTP czyli HTTPS. 
  • Basic authentication nie jest odporne na ataki CSRF (cross-site request forgery)

Niniejszy post przedstawia jak zaimplementować taką autentykację w naszym ASP.NET Web API (post nie dotyczy ASP.NET Web API 2, które jest prostsze i zawiera już zaimplementowane techniki autentykacji serwisu bez konieczności pisania dodatkowego kodu).

AuthorizeAttribute 

Implementacja basic authentication będzie polegała na stworzeniu własnego atrybutu do autoryzacji. W pierwszej kolejności jednak musimy napisać metodę pomocniczą, która wyłuska nam credentials (nazwę użytkownika i hasło) z wiadomości, która przychodzi do serwera. Metoda taka może wyglądać następująco:

private Credentials ParseAuthorizationHeader(string authHeader)
{
   string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(authHeader)).Split(new[] { ':' });
   if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0]) || string.IsNullOrEmpty(credentials[1]))
      return null;
   return new Credentials() { Username = credentials[0], Password = credentials[1], };
}
Teraz wystarczy napisać naszą klasę, która będzie dziedziczyła po "AuthorizeAttribute":
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
   private const string BasicAuthResponseHeader = "WWW-Authenticate";
   private const string BasicAuthResponseHeaderValue = "Basic";

   protected IPrincipal CurrentUser
   {
      get { return Thread.CurrentPrincipal as IPrincipal; }
      set { Thread.CurrentPrincipal = value as IPrincipal; }
   }

   public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
   {
      try
      {
         AuthenticationHeaderValue authValue = actionContext.Request.Headers.Authorization;
         Credentials parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
         if (parsedCredentials != null)
         {
            this.CurrentUser = new DummyPrincipalProvider().CreatePrincipal(parsedCredentials.Username, parsedCredentials.Password);
            if (!CurrentUser.Identity.IsAuthenticated)
            {
               actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
               actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
               return;
            }
         }
      }
      catch (Exception ex)
      {
         actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
         actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
         return;
      }
  }
}
W powyższej implementacji korzystam z klasy "DummyPrincipalProvider", która jest dziedziczy z IPrincipalProvider i jest moją "fake'ową" implemetacją dostarczyciela tożsamości. Wygląda następująco:
public class DummyPrincipalProvider : IProvidePrincipal
{
   private const string Username = "username";
   private const string Password = "password";

   public IPrincipal CreatePrincipal(string username, string password)
   {
      if (username != Username || password != Password)
      {
         return null;
      }
      var identity = new GenericIdentity(Username);
      IPrincipal principal = new GenericPrincipal(identity, new[] { "User" });
      return principal;
    }
 }
W tym miejscu jednak powinna być implemetacja odpowiedniego dortarczyciela tożsamości, np. jeśli dane użytkowników przechowywane są bazie to wtedy najlepszym rozwiązaniem będzie użycie gołego ADO.NET lub z wykorzystaniem EntityFramework do pobrania takich danych z bazy danych. Mając tak napisany atrybut, wystarczy teraz, że klasę lub metodę, którą chcemy zabezpieczyć udekorujemy tym atrybutem:
[CustomAuthorizeAttribute]
[HttpGet, HttpHead]
public Product Get(int id)
{
   var product = productRepository.Get(id);
   if (product == null)
      throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
   return product;
}