Blog o tematyce związanej z platformą .NET i szeroko pojętym programowaniem. Znajdziesz tu informacje nt. platformy .NET, języka C#, wiadomości o wzorcach projektowych oraz tworzeniu poprawnej architektury oprogramowania.
Na początku kwietnia zostało opublikowane uaktualnienie do Visual Studio 2012 z numerkiem 2.
Co nowego?
Przede wszystkim rozwój narzędzi przeznaczonych do zarządzania, planowania projektu. Dodano nowe funkcjonalności do tablicy kanbanowej. Dodano także możliwość tagowania elementów roboczych co ułatwia zarządzanie elementami w projekcie.
W samym Visual Studio wprowadzono możliwość grupowania testów na podstawie klas, jak i możliwość tworzenia list testów. Dzięki takiemu rozwiązaniu, możliwe jest stworzenie kilku list testów.
Kolejnym bardzo fajnym narzędziem jest Code Map - o tym narzędziu mam zamiar napisać osobny post. Narzędzie usprawnia proces debugownaia i odnajdowania problemów w naszej aplikacji.
Zachęcam do aktualizacji i podzielenia się swoimi opiniami nt. nowej aktualizacji.
Polecam także filmik pokazujący na żywo nowości wprowadzone w Update 2:
To wszystko co jest wymagana do generowania i wyświetlania zawartości takiej metody.
Pozostaje jeszcze jedna kwestia. Jak wiadomo, każdą publiczną metodę w kontrolerze można wywołać z paska przeglądarki. Jeżeli jednak nie chcemy aby naszą metodę, która ma zostać wywołana tylko na innej strony, możemy zastosować atrybut [ChildActionOnly]:
O walidacji pisałem już wcześniej w kursie o ASP.NET MVC 2.
W wersji trzeciej i czwartej dodano nowe możliwości walidacji o których napiszę w tym poście.
1. Atrybuty
Atrybuty opisywałem w przypadku wersji drugiej ASP.NET MVC - nie będę więc powielał już napisanego tekstu.
Dla przypomnienia tylko w jaki sposób je dodajemy do naszego modelu:
Dodano nowe atrybuty, wśród nich m.in: EmailAddress, Url, CreditCard, Phone, Remote, Display, DisplayFormat.
Ostatni atrybut - Remote pozwala na napisanie kodu, który wykonuje walidację po stronie serwera bez potrzeby wysyłania całego formularza do serwera. Bardzo dobry przykład ilustrujący zastosowanie tego atrybutu można znaleźć w msdn http://msdn.microsoft.com/en-us/library/gg508808%28v=vs.98%29.aspx
2. Napisanie własnego atrybutu walidacji
Jeżeli kilka właściwości w modelu wymaga tego samego sposobu walidacji, można go zamknąć w atrybucie dziedziczącym po klasie ValidationAttribute:
Code:
publicclassCustomValidationAttribute : ValidationAttribute
{
public CustomValidationAttribute() : base("{0} is not valid")
{
}
protectedoverrideValidationResult IsValid(objectvalue, ValidationContext validationContext)
{
//Validacjareturn ValidationResult.Success;
}
}
W naszej klasie nadpisujemy metodę IsValid i umieszczamy w niej kod odpowiedzialny za walidację wartości. w przypadku powodzenia zwracamy wartość Success, w innym przypadku zwracamy obiekt ValidationResult z wiadomością błędu.
3. Interfejs IValidatableObject
Zaletą tego rozwiązania jest to, że mamy dostęp do całego obiektu modelu w momencie przeprowadzania walidacji. W przypadku atrybutów możemy przeprowadzić walidację więcej niż jednego pola na raz, jednak korzystając z interfejsu IValidatableObject jest to o wiele prostsze.
Przykład:
Pole SecreetField zostało za komentowane (nie pojawi się w źródłach wygenerowanego dokumentu).
W kontrolerze wprowadzamy prosty kod który uaktualni obiekt użytkownika na podstawie przekazanych przez Binding wartości:
Code:
[HttpPost]
publicActionResult Edit(ApplicationUser user)
{
if (ModelState.IsValid)
{
var u = userService.GetUserById(user.Id);
UpdateModel(u);
}
return RedirectToAction("GetUsers");
}
Rozwiązanie można powiedzieć książkowe - poza jednym szczegółem - brakuje SaveChanges na obiekcie Context, którego akurat w tym przypadku nie mam (nie korzystam z bazy danych a ze statycznej kolekcji).
Wydawałoby się że powyższy przykład jest poprawny. Jednak jest jedna rzecz którą przeoczyliśmy podczas tworzenia tego rozwiązania - nasi użytkownicy. Zobaczmy co mogłoby się stać, gdyby ktoś chciał wykorzystać aplikację w sposób który nie chcemy:
Przepraszam za słabą jakość, ale chodzi tutaj o samo sedno problemu. Mianowicie jeżeli użytkownik będzie chciał zaatakować naszą stroną i w naszym modelu znajdzie się pole typu IsAdmin, użytkownik może przesłać ten parametr bezpośrednio do mechanizmu bindowania (np. tak jak ja za pomocą QueryString).
W jaki sposób możemy zapobiec takiemu zachowaniu? Otóż istnieje kilka rozwiązań:
1. Stworzenie osobnych modeli do edycji, wyświetlania
2. Skorzystanie z atrybutu Bind:
Kolejne pola, które nie mają brać udziału w bindowaniu wymieniamy po przecinku. Możemy oczywiście także wskazać, które pola mają brać udział w bindowaniu.
3. Metoda UpdateModel jako jeden z argumentów przyjmuje tablicę pól, które mają zostać uaktualnione:
29 marca oficjalnie zakończyłem ścieżkę certyfikacyjną - przynajmniej na ten moment :)
Efektem nauki jest zdanie 4 egzaminów MCTS, oraz dwóch MCPD.
70-513
Windows Communication Foundation - egzamin prosty, chociaż w niektórych przypadkach czytanie XMLów może zająć trochę więcej czasu. Materiały z których się uczyłem to Training Kit dla .NET 3.5, tematy które nie są zawarte w podręczniku można doczytać w internecie. Warto też przejrzeć materiały zebrane w formie linków na stronie http://www.jamesjfoster.com/blog/2010/resource-links-for-70-513-wcf-certification-exam/. Wiedza ta wystarcza w 100% do zdania egzaminu.
70-518
Egzamin różni się od pozostałych tym, że kładzie nacisk na znajomość ograniczeń i możliwości poszczególnych rozwiązań Microsoft podczas tworzenia aplikacji desktopowych. Większość pytań dotyczy tworzenia systemów i pytań mających na celu określenie wyboru prawidłowego frameworka / rozwiązania danego zagadnienia.
70-515
Tworzenie aplikacji webowych w ASP.NET WebForms oraz MVC. Pierwszym zastrzeżeniem jakie mam co do egzaminu to użycie MVC w wersji 2.0. Mamy już 4 wersję tego frameworka i raczej żadnego nowego projektu nie rozpoczniemy pisać w czymś co powstało kilka lat wstecz. Jeżeli chodzi o poziom pytań - zróżnicowany od bardzo prostych i wręcz oczywistych aż do zagadnień, których często nie wykorzystuję.
70-519 Egzamin który ma tę samą formę co 70-518. Najdłuższy ze wszystkich, największa ilość pytań którą do tej porty otrzymałem - 78. Podczas egzaminu dwa przypadki systemów do których zostało przygotowanych 14 pytań. Ogólnie egzamin podobał mi się, ciekawe pytania i zagadnienia. Jeżeli ktoś pracuje przy tworzeniu aplikacji webowych po przeczytaniu materiałów zawartych w Training Kit i skorzystaniu z linków do materiałów zawartych w nim, nie będzie mieć problemów ze zdaniem ich.
Obecnie nie zamierzam przystępować do kolejnych egzaminów. Sama certyfikacja posłużyła mi głównie w celu segregacji posiadanej wiedzy, nauczeniu się nowych metod rozwiązywania często spotykanych problemów.
W sieci można spotkać się z opiniami, że certyfikacja nie ma sensu. Nie zgodzę się z tymi stwierdzeniami. W wielu przypadkach samo podejście do egzaminu zmusza nas do przeczytania odpowiednich materiałów, dzięki którym być może nauczymy się rozwiązywać dane problemy w lepszy, szybszy i bardziej przenośny sposób.
Wszystkim, którzy są w trakcie bądź też przymierzają się do certyfikacji życzę wytrwałości i sukcesów.
Parsowanie HTML chociaż wydaje się rzeczą trywialną potrafi przysporzyć wielu problemów. Związanie jest to nie tyle ze skomplikowaniem zagadnienia co z formatem w jakim otrzymujemy dane.
Szukając tagu w wielu przykładach możemy natrafić na nie zamknięte tagi, niepoprawnie sformatowane znaczniki itp.
Do projektu bibliotekę można dodać poprzez ściągnięcie odpowiedniej dll z codeplex, bądź korzystając z NuGet-a:
PM> Install-Package HtmlAgilityPack
Po zainstalowaniu biblioteki możemy przystąpić do przetwarzania HTML:
Code:
using System;
using System.Collections.Generic;
using System.Net;
using HtmlAgilityPack;
using System.Linq;
namespace HtmlAgilityPack_Sample
{
classProgram
{
privatestaticvoid Main(string[] args)
{
var webClient = newWebClient();
string pageContent = webClient.DownloadString(@"http://www.onet.pl/");
var htmlDocument = newHtmlDocument();
htmlDocument.LoadHtml(pageContent);
foreach (HtmlNode link in htmlDocument.DocumentNode.SelectNodes("//a[@href]"))
{
HtmlAttribute att = link.Attributes["href"];
Console.WriteLine(att.Value);
}
foreach (var div in htmlDocument.DocumentNode.SelectNodes("//div"))
{
HtmlAttribute classAttribute = div.Attributes["class"];
if (classAttribute != null)
{
Console.WriteLine(classAttribute.Value);
}
}
}
}
}
Przykładowy kod powyżej pokazuje w jaki sposób pobrać ze strony wszystkie linki i znaczniki div. Zapytania pisane są w języku XPath.
Biblioteka jest dostępna jako opensource - możemy więc pobrać kod i dodawać nową funkcjonalność.
Na temat biblioteki można znaleźć krytyczne wypowiedzi, dotyczące m.in.:
w przypadku gdy metoda SelectNodes() nie zwróci rezultatów, zwracany jest null co uniemożliwia użycie takiego rezultatu jako rezultatu wyrażenia np. pętli foreach
kiedy szukamy dzieci podanego węzła, metoda SelectNode szuka od początku dokumentu (aby szukała od aktualnego węzła należy podać parametr descendant::)
Z moich testów wynika, że biblioteka dobrze radzi sobie z parsowaniem nawet bardzo kiepskiej jakości kodu HTML. Wyżej wymienione problemy można samemu poprawić (kod jest dostępny). Zachęcam do eksperymentowania i podzieleniem się uwagami na temat biblioteki.