Express App Framework – walidacja danych
Dane przed wysÅ‚aniem do bazy danych, musimy poddać walidacji. Standardowe przypadki to „pole nie może być puste”, „pole musi mieć unikatowÄ… wartość”, czy też bardziej zaawansowane przypadki, w których używamy wyrażeÅ„ regularnych. W Express App Framework zadanie to realizujemy w prosty sposób, używajÄ…c do tego gotowego silnika. Å»eby nie przedÅ‚użać wpisu, przejdźmy od razu do rzeczy.
Na początek dodajmy przestrzeń nazw DevExpress.Persistent.Validation .
Przypadek 1, „pole nie może być puste”:
Aby wymusić wypełnienie pola, musimy podać atrybut przed właściwością:
[RuleRequiredField("Name",DefaultContexts.Save, "Pole nie może być puste")]
public string Name
{
get { return _name; }
set { SetPropertyValue("Name", ref _name, value); }
}
Pierwszym parametrem jest unikatowa nazwa, następnie w jakim kontekście chcemy użyć walidacji oraz treść komunikatu. Myślę, że banalnie proste.
Przypadek 2, „Istnieje już taki obiekt/nazwa w bazie”:
Można się domyślić, że różnica będzie polegała tylko na zmianie atrybutu
Dodamy jednak opcjonalnie, żeby przepuszczał puste ciągi.
[System.ComponentModel.DisplayName("ImiÄ™")]
[RuleUniqueValue("Name", DefaultContexts.Save, "Istnieje już takie imie", SkipNullOrEmptyValues = false)]
public string Name
{
get { return _name; }
set { SetPropertyValue("Name", ref _name, value); }
}
Przypadek 3, „podaj wartość z zakresu od-do”:
[System.ComponentModel.DisplayName("Wiek")]
[RuleRange("Age",DefaultContexts.Save,18,30,"Podaj wiek z przedziału 18-30")]
public int Age
{
get { return _age; }
set { SetPropertyValue("Age", ref _age, value); }
}
Kod chyba nie wymaga tłumaczenia.
Ostatni, czwarty przypadek jaki chciałbym pokazać, to walidacja przy pomocy wyrażeń regularnych.
[RuleRegularExpression("Email", DefaultContexts.Save, @"^[a-zA-Z0-9.\-_]+@[a-zA-Z0-9\-.]+\.[a-zA-Z]{2,4}$", "Nieprawidłowy format adresu mail")]
public string Email
{
get { return _email; }
set { SetPropertyValue("Email", ref _email, value); }
}
Myślę, że te cztery kluczowe sposoby walidacji powinny wystarczyć, żeby zapanować nad nawet najbardziej topornymi użytkownikami. Po raz kolejny ukazuję to prostotę wytwarzania oprogramowania przy pomocy Express App Framework.
Na koniec chciałbym pokazać jak wygląda, wywołanie błędu po źle wprowadzonych danych w asp:
W aplikacji windows forms jest to po prostu popup.
Express App Framework – ListView i DetailView
Dzisiaj chciałbym Wam pokazać gdzie możecie zmieniać domyślnie utworzone widoki dla ListView oraz DetailView. Przypominam, że ListView to grid który widzimy po wejściu w zakładkę naszego nowego obiektu. Dla naszej testowej klasy z poprzedniego projektu wygląda on następująco:
Zacznijmy od tego, że chcielibyśmy aby Nasza Klasa była w menu, w kategorii Moje klasy i w listview chcielibyśmy tylko wyświetlać imię oraz wiek. Nic prostszego. Jeżeli chcemy aby zmiany w widoku oraz menu były uwzględniane w projekcie asp.net oraz windows forms, w głównym module przechodzimy do Model.DesignedDiffs.xafml . Jest to tak naprawdę jeden wielki plik xml z ustawieniami.
Wejdźmy w NavigationItems—>Items—>PPM—>AddNavigationItem .
Jako Caption ustawmy Nasza klasa, id cokolwiek. Widzimy, że dodatkowo możemy wybrać index (0 – jako domyÅ›lne sortuje alfabetycznie), ikonÄ™ itp.
Z nawigacji default kopiujemy nasza klasa, wklejamy do naszej gałęzi a stamtąd usuwamy.
Ok, menu mamy załatwione, teraz widoki. Przechodzimy do zakładki Views i wyszukujemy TestClass_ListView. Rozwijamy jej kolumny i możemy usunąć te które nas nie interesują. My sobie zostawimy, tak jak wspominałem imię i wiek. Przy okazji widzimy po prawej stronie, dla każdego pola multum właściwości które możemy dodatkowo poustawiać.
Teraz zajmijmy się naszym widokiem DetailView, czyli tym który widzimy przy dodawaniu, edycji bądź usuwaniu obiektu. Dla naszej klasy wygląda on następująco:
Widzimy, że ukÅ‚ad jest co najmniej nieelegancki. Przejdźmy do Views i rozwiÅ„my TestClass_DetailView i wejdźmy w layout. Po prawej stronie PPM—->Customize Layout. I teraz to już zabawa klockami i Wasza inwencja twórcza
Ja przykładowo ułożyłem sobie to tak:
W efekcie otrzymałem:
Dzisiaj mogliście zobaczyć jak banalnie prosto można zarządzać widokami oraz menu w Express App Framework.
Do następnego wpisu!
Express App Framework – pierwsza klasa biznesowa
Witam po długiej przerwie. Dzisiaj chciałbym pokazać Wam, jak stworzyć klasę biznesową, na podstawie której powstaje widok oraz tabela w bazie. Użyje różnych typów danych, żebyście mogli zobaczyć jakie są domyślne edytory dla nich w Express App Framework. Oczywiście same edytory jak i widoki możemy zmieniać. O ile te drugie to prosta sprawa, to z edytorami nie jest już to takie oczywiste. Przejdźmy do rzeczy. Mając otwarty projekt z poprzedniego wpisu (do pobrania tutaj), dodajmy do modułu głównego klasę TestClass.cs -koniecznie wybierzmy typ DomainObject.
Ważne jest to dlatego, że ona domyślnie dziedziczy po BaseObject, a to daje nam metody wirtualne oraz to, że będzie ona widoczna w naszych modułach jako klasa biznesowa. Na początku dodajmy dwa atrybuty dla naszej klasy:
[System.ComponentModel.DisplayName("Nasza klasa")]
[DeferredDeletion(false)]
O co chodzi z tym DeferredDeletion. Jest to ważny atrybut i należy już na samym poczÄ…tku zastanowić siÄ™ jakÄ… droga pójdziemy. Jak wiemy XAF domyÅ›lnie udostÄ™pnia nam kontrolery zapisu, edycji, usuwania itd. UstawiajÄ…c DeferredDeletion na false bÄ™dziemy usuwać nasze dane z bazy „na zawsze”. Musimy wtedy sami np. w metodzie OnSaving zadbać o usuniÄ™cie wszystkich zależnych rekordów. Ustawienie parametr na true zwalnia nas z tego obowiÄ…zku. RzeczywiÅ›cie w bazie ustawiona zostanie w polu GCRecord jakaÅ› losowÄ… wartość. Dla XAF’a jest to znak, że tej krotki ma nie wyÅ›wietlać. Wybór należy do Was.
Czas uzupełnić naszą klasę właściwościami, na podstawie których powstanie widok oraz tabela w bazie. Powinna ona wyglądać następująco:
using System;
using System.ComponentModel;
using System.Drawing;
using DevExpress.Xpo;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Xpo.Metadata;
namespace Blog.Module
{
[DefaultClassOptions]
[System.ComponentModel.DisplayName("Nasza klasa")]
[DeferredDeletion(false)]
public class TestClass : BaseObject
{
private string _name;
private int _age;
private bool _isNew;
private string _description;
[System.ComponentModel.DisplayName("ImiÄ™")]
public string Name
{
get { return _name; }
set { SetPropertyValue("Name", ref _name, value); }
}
[System.ComponentModel.DisplayName("Wiek")]
public int Age
{
get { return _age; }
set { SetPropertyValue("Age", ref _age, value); }
}
[System.ComponentModel.DisplayName("Nowy")]
public bool IsNew
{
get { return _isNew; }
set { SetPropertyValue("IsNew", ref _isNew, value); }
}
[System.ComponentModel.DisplayName("Opis")]
[Size(SizeAttribute.Unlimited)]
public string Description
{
get { return _description; }
set { SetPropertyValue("Description", ref _description, value); }
}
[System.ComponentModel.DisplayName("Image")]
[Size(SizeAttribute.Unlimited), Delayed, ValueConverter(typeof(ImageValueConverter))]
[ImageEditor(DetailViewImageEditorMode = ImageEditorMode.PictureEdit,
DetailViewImageEditorFixedWidth = 150, DetailViewImageEditorFixedHeight = 150)]
public Image Image
{
get { return GetDelayedPropertyValue<Image>("Image"); }
set { SetDelayedPropertyValue<Image>("Image", value); }
}
public TestClass(Session session) : base(session) { }
}
}
Odpalmy projekt (ja u siebie odpaliłem win), po zalogowaniu powinniśmy dostać następujące okno:
To, co widzimy to ListView. Oczywiście pola, które są wyświetlane w gridzie są edytowalne. Wybierając nowy rekord, przechodzimy do DetailView i tam już widzimy, jak są domyślnie reprezentowane poszczególne typy danych. Cały interfejs, rozmieszczenie, menu itd jest jak najbardziej edytowalne. Ale o tym powiemy sobie w następnym wpisie.
PodsumowujÄ…c… ZrobiliÅ›my dzisiaj klasÄ™ biznesowÄ…, na podstawie której powstaÅ‚a tabela w bazie (możecie sobie sprawdzić). OtrzymaliÅ›my kompletny widok do edycji tej tabeli. Możemy usuwać, dodawać, edytować, wyszukiwać dane. Dużo siÄ™ nie namÄ™czyliÅ›my
W następnych wpisach pokażę, jak ułożyć taki widok, spolszczyć domyślne kontrolery, walidację czy relację pomiędzy tabelami. Zacznie się ciekawie
Kolejny wpis w weekend, zapraszam!
Dzisiejszy cały projekt do pobrania tutaj. Jakby ktoś zapomniał hasła i nazwy użytkownika (albo co gorsza nie czytał poprzedniego wpisu
) znajdzie te dane w klasie Updater.cs .
Express App Framework – Security
Po tym, jak zapoznaliÅ›cie siÄ™ z architekturÄ… xaf’a wypadaÅ‚oby napisać jakÄ…Å› prostÄ… aplikacjÄ™. Dzisiaj pokażę, jak dołączyć zabezpieczania do projektu i jak stworzyć użytkowników w kodzie.
Po zainstalowaniu Frameworka dostajemy do wyboru nowy typ projektów:
My wybieramy Application Solution v 10.1, ponieważ bÄ™dziemy tworzyć nasz formularz zarówno na Windows Forms jak i ASP.NET . W solution explorer stworzyÅ‚o nam siÄ™ pięć modułów. Dzisiaj bÄ™dÄ™ omawiaÅ‚ tylko logowanie, tworzenie użytkowników i nadawanie im praw. Musimy wiedzieć, że wszystkie klasy biznesowe w projekcie bÄ™dziemy tworzyć w module głównym, co nam zagwarantujÄ™, że bÄ™dÄ… one widoczne zarówno dla moduÅ‚u odpowiedzialnego za Windows Forms, jak i ASP.NET . Tak samo jest z innymi ustawieniami, jak np. widok. Raz ustawiony jest „dziedziczony” na dwie platformy. OczywiÅ›cie nie musimy tak robić, możemy tworzyć te widoki niezależnie.
Stwórzmy sobie bazę danych. Nie będę opisywał, jak to zrobić-informacje na ten temat znajdziecie tutaj.
Mając bazę danych, przejdźmy do modułu .win i wejdźmy w WinApplication.cs . Dostaniecie komunikat żebyście przebudowali projekt, zróbcie to i w końcu ujrzymy okno:
Przepraszam za jakość obrazków, ale takie mam możliwoÅ›ci umieszczenia na blogu (po klikniÄ™ciu macie już normalny widok). Ok, dzisiaj interesujÄ… nas sekcje Connection oraz Security. Jak widzimy, dodatkowo można tam zarzÄ…dzać moduÅ‚ami, kontrolerami oraz klasami biznesowymi, o czym w nastÄ™pnych wpisach. W toolbox’ie pojawiÅ‚y nam siÄ™ elementy do poszczególnych sekcji. My zostawimy SqlConnection, klikamy na niego i w properties wklejamy connection string’a do naszej bazy. Mamy już połączenie. Do dziaÅ‚u Security przeciÄ…gnijmy z toolbox’a SecurityComplex oraz AuthenticationStandard. SÄ… to gotowe, wbudowane moduÅ‚y zabezpieczeÅ„ naszej aplikacji.
SecuritySimple – moduÅ‚u tego używamy wtedy, kiedy nasza aplikacja ma dwie role: Admin, User. Wtedy tylko każdemu użytkownikowi ustawiamy wÅ‚aÅ›ciwość isAdmin. Administratorzy majÄ… dostÄ™p do wszystkich operacji na obiektach użytkownika. W SecuritySimple do tworzenia użytkowników sÅ‚użą dwie klasy BasicUser oraz SimpleUser. ZasadniczÄ… różnicÄ… pomiÄ™dzy nimi jest to, że w BasicUser pole id jest typu integer, natomiast w SimpleUser id to GUID.
SecurityComplex – moduÅ‚ ten wykorzystujemy, kiedy nasza aplikacja używa ról, praw dostÄ™pu itd. Tam do tworzenia użytkowników sÅ‚uży klasa User.
AuthenticationStandard- standardowy panel do logowania. np. dla aplikacji asp.net ma wbudowany mechanizm, że po trzecim błędnym logowaniu zamyka okno itp. W każdym bądź razie, proces logowania mamy obsłużony i to zarówno dla modułu SecuritySample oraz SecurityComplex.
AuthenticationActiveDirectory – to wielki plus Express App Framework, który udostÄ™pnia nam wykorzystanie praktycznie z automatu Active Directory.
My dzisiaj zajmiemy się SecurityComplex oraz AuthenticationStandard. Może i nie uwierzycie, ale jeżeli uruchomicie projekt .win, bądź .web to mamy już gotową aplikacje. Nawet bez tych wstępnych ustawień które porobiliśmy. Jeżeli byśmy np. zapomnieli ustawić connectionstring, xaf wygeneruje nam bazę lokalną. Pewnie teraz większość z Was uruchomi projekt, bo mi nie wierzy
. Uruchamiając trafimy na panel logowanie, ale my nie mamy jeszcze użytkowników w bazie! Tutaj z pomocą przychodzi nam klasa Updater.cs z głównego modułu. Klasa ta zawiera metodę UpdateDatabaseAfterUpdateSchema, która jest wywoływana za każdym razem, kiedy nasz program uruchamiamy w trybie debugowania. Tak więc, metoda ta przeznaczona jest do tworzenia wstępnych danych podczas wdrażania aplikacji lub aktualizacji. Użyjemy SecurityComplex, ponieważ chciałbym pokazać w kodzie jak poustawiać dostęp do obiektów, stworzyć rolę i użytkowników. Mimo, że role ograniczymy do administratora i użytkownika(czyli klasyczny przypadek wykorzystania SecuritySimple).
Tworzenie użytkownika:
User administrator = Session.FindObject<User>(
new BinaryOperator("UserName", "Administrator"));
if (administrator == null)
{
administrator = new User(Session);
administrator.UserName = "Administrator";
administrator.FirstName = "Administrator";
administrator.SetPassword("123");
}
Najpierw musimy sprawdzić, czy danego użytkownika nie ma już w bazie, za co odpowiadają dwie pierwsze linie. Kolejne linie, to tworzenie użytkownika. Korzystając z AuthenticationStandard, musimy nadać hasło. Podobnie postępujemy ze zwykłym użytkownikiem. Dodanie roli to również sprawdzenie, czy takowa istnieje już w bazie i utworzenie jej:
Role adminRole = Session.FindObject<Role>(
new BinaryOperator("Name", "Administrators"));
if (adminRole == null)
{
adminRole = new Role(Session);
adminRole.Name = "Administrators";
}
Tak samo tworzymy role userRole. Kolejne zadanie, to skasowanie nadanych już uprawnień dla danych ról, jeżeli by istaniały:
while (adminRole.PersistentPermissions.Count > 0)
{
Session.Delete(adminRole.PersistentPermissions[0]);
}
while (userRole.PersistentPermissions.Count > 0)
{
Session.Delete(userRole.PersistentPermissions[0]);
}
Następnie przypisanie danym rolom uprawnień względem obiektów oraz modelu aplikacji, oraz zapisanie tych ról.
adminRole.AddPermission(new ObjectAccessPermission(typeof(object), ObjectAccess.AllAccess)); adminRole.AddPermission(new EditModelPermission(ModelAccessModifier.Allow)); adminRole.Save(); userRole.AddPermission(new ObjectAccessPermission(typeof(object), ObjectAccess.AllAccess)); userRole.AddPermission(new ObjectAccessPermission(typeof(User), ObjectAccess.ChangeAccess, ObjectAccessModifier.Deny)); userRole.AddPermission(new ObjectAccessPermission(typeof(Role), ObjectAccess.AllAccess, ObjectAccessModifier.Deny)); userRole.AddPermission(new EditModelPermission(ModelAccessModifier.Deny)); userRole.Save();
Jak widzimy administrator ma peÅ‚en prawa, natomiast zwykÅ‚emu użytkownikowi blokujemy dostÄ™p do modelu. DziÄ™ki temu np. odpalajÄ…c aplikacje Windows Forms, zwykÅ‚y użytkownik nie może „na żywo” ukÅ‚adać/zmieniać wyglÄ…du danych obiektów (details view). Zarówno ObjectAccess jak i ModelAccesModifier to typ Enum, dlatego chcÄ…c np. ograniczyć dostÄ™p tylko do odczytu i zapisu, musimy posÅ‚użyć siÄ™ alternatywÄ…. OczywiÅ›cie użytkownicy majÄ… panel do zarzÄ…dzania rolami, uprawnieniami, użytkownikami, pamiÄ™tajmy natomiast, że my tworzymy tutaj ustawiania poczÄ…tkowe. Ostatnim krokiem jest dodanie stworzonych użytkowników do roli oraz zapisanie ich.
administrator.Roles.Add(adminRole); user.Roles.Add(userRole); administrator.Save(); user.Save();
Teraz, po odpaleniu aplikacji, możemy już się śmiało zalogować
i w zależności od tego, czy będziemy zalogowani jako admin czy jako user, będziemy mieli dostęp do odpowiednich obiektów typu np. Roles. Jak widzimy, mamy już gotowy formularz wprowadzania danych, zarządzania nimi. Jeżeli chcielibyśmy odpalić aplikacje asp.net, to WebApplication.cs znajdziecie w module .Web w folderze ApplicationCode. Zróbcie ustawienia tak, jak na początku artykułu i odpalcie projekt. Oczywiście możecie podejrzeć bazę danych xaf wygenerował nam już parę tabel
To pierwsze możliwości Express App Framework. W następnym wpisie pokażę, jak stworzyć klasę biznesową, na podstawie której generuje się widok oraz tabela w bazie danych. Czyli pomału zacznie robić się ciekawie.
Gotowy projekt z caÅ‚ym kodem jest do pobrania tutaj. PamiÄ™tajcie, żeby zmienić connection string’a !!!.
Kolejny wpis już niedługo.
Express App Framework – Architektura
Dzisiaj chciaÅ‚bym, możliwie krótko, przedstawić architekturÄ™ XAF’a. Zanim zacznÄ™ wpisy techniczne, warto chociaż w minimalnym stopniu wiedzieć jak jest zbudowany ten Framework.
Sam XAF to narzędzie wspomagające tworzenie aplikacji na windows forms oraz asp.net. Modułowa konstrukcja pozwala korzystać z wielu wbudowanych już modułów oraz pisać własne. To przekłada się, w dużym stopniu, na szybsze i wydajniejsze tworzenie oprogramowania. Dodatkowo wykorzystuje on metodę scaffoldingu, co pozwala nam skupić się na logice biznesowej.
Przejdźmy teraz do tytułowej architektury. Wizualnie przedstawia się tak:
Omówmy sobie pokrótce każdy z elementów:
XPO – Å›wiat .NET-u, pomijajÄ…c Ado.Net, przyzwyczaiÅ‚ nas do tego, że zamiast bezpoÅ›redniej interakcji z bazÄ… danych mamy zmapowane tabele na obiekty. Tutaj takÄ… warstwÄ™ Å›wiadczy nam XPO (eXpress Persistent Objects). WedÅ‚ug twórców XAF’a (devexpress), XPO zapewnia niezawodność i elastyczność w przechowywaniu danych, co majÄ… potwierdzone i przetestowane, ponieważ XPO przez lata istniaÅ‚o jako samodzielny produkt.
BUSINESS CLASS LIBRARY- jest to jeden z najistotniejszych elementów. Na podstawie tych klas powstajÄ… tabele w bazie. Definiujemy w nich pola, relacje, logikÄ™ biznesowÄ… etc. Business class library dziedziczÄ… po BaseObject, otrzymujÄ…c tym samym metody wirtualne typu OnSaved, OnLoading itd…
Application Specific Business Classes- najprościej mówiąc, są to wszystkie klasy, które wspomagają pracę klas biznesowych.
Controller Library – kontrolery zarzÄ…dzajÄ… przepÅ‚ywem aplikacji. SÄ… one odpowiedzialne za interakcje z użytkownikiem koÅ„cowym. Nawet najprostsze aplikacje zbudowane z XAF’a korzystajÄ… z wielu wbudowanych kontrolerów. DziÄ™ki nim możemy np. dodawać rekordy, usuwać już istniejÄ…ce, wykonywać wyszukiwanie peÅ‚no tekstowe itd. co mamy domyÅ›lnie zdefiniowane i udostÄ™pnione.
Application Specific Controllers – podobnie jak Application Specyfic Business Classes są to niestandardowe kontrolery do niestandardowych zadań
View/Raports -view czyli widok, interfejs do zarządzania danymi, który tworzy się automatycznie. Raporty tworzymy ręcznie i to są już wydruki, prezentacja danych.
Application Modell – jest to jeden wielki zbiór informacji, zapisany w postaci pliku xml, w którym mamy informacje dotyczÄ…ce interfejsu, edytorów, ustawieÅ„ konfiguracyjnych itd. Obok klas biznesowych to tutaj spÄ™dzimy dużą część czasu, tworzÄ…c naszÄ… aplikacje. OczywiÅ›cie xml jest konfigurowalny poprzez interfejs udostÄ™pniony przez Framework. Może siÄ™ zdarzyć, że popsujemy coÅ› w tym modelu (np. podczas pracy grupowej), no to wtedy od razu mówiÄ™, że nie jest piÄ™knie
Oczywiście, tak jak widać, to wszystko mamy udostępnione na platforme Windows Forms oraz Asp.NET .
Mam nadzieje, że dobrnąłeś, drogi Czytelniku, do końca
Na koniec chciałbym zaznaczyć, że schemat z architekturą został pobrany ze strony producenta i nie jest moją własnością.
Witam
Kolejny blog w Internecie. Kolejny o .NET. Pytanie czy to źle, czy jednak dobrze. W każdym bądź razie będzie to miejsce gdzie można zasięgnąć dodatkowej informacji. Ja jednak swoich wpisów nie chciałbym rozpoczynać od takich standardowych i oklepanych tematów jak korzystać z grida czy jak załadować zdjęcie na serwer. Wstępnie swoje artykuły chciałbym poświecić myślę dość ciekawemu Frameworkowi a mianowicie Express App Framework. Nie spotkałem się z polskojęzycznym blogiem o tym narzędziu (jeżeli ktoś takowego piszę to chętnie bym poczytał i poproszę o adres).  Swego czasu miałem okazje pracować z xaf’em i wiem, że początki są trudne (trzeba się przestawić na trochę inne myślenie). Sam xaf nie zawsze jest intuicyjny, wiele rzeczy nam ułatwia, robi z automatu, o czym się przekonamy przy wpisie o relacjach pomiędzy tabelami. W kolejnym artykule chciałbym bliżej przedstawić, czym jest xaf, do czego możemy go wykorzystać i jak wygląda jego architektura. W następnych przejść już do rzeczy praktycznych, czyli pisać jakieś aplikacje. Na początku tego bloga chciałbym zaznaczyć, że nie jestem jakimś specjalistą z zakresu Express App Framework, ale wiem, z jakimi trudnościami spotyka się początkowy użytkownik i z czym może mieć problemy. Przy okazji sam chcę się rozwijać z tego zakresu, ucząc się i przekazywać nowo nabytą wiedzę na blogu, czyli Wam.  Do następnego wpisu, który będzie już JUTRO!










