Jurnal de programator
99,9% Microsoft
Send mail to the author(s)
Home | Mini tools List| Blog carti| ASP.NET MVC ebook| tutorial 3.5| Subscribe by Email | twitter| linkedin | youtube | interviu
Monday, May 24, 2010


C# si null for decimal

Fara sa compilati, vedeti ce output da codul acesta:

decimal? v = 100;
            Console.WriteLine(v);
            decimal? x = null;
            x += v.Value;
            Console.WriteLine(x);

Ok, e clar raspunsul avind in vedere intrebarea ...

.NET | c# | quiz
Monday, May 24, 2010 2:36:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, May 03, 2010


Baby steps cu VS2010 si .NET 4

Sunt pe cale sa termin un ebook despre ce poti face cu Visual Studio 2010 si .NET 4.0 . Ca de obicei, o sa fie free  - si, ca de obicei, nu pot sa il termin singur si am nevoie de ajutorul vostru. O sa incerc sa fie gata inainte de

Mai sunt de scris capitole despre

TODO VS2010 : WPF, Workflow,Silverlight, Azure, Reporting , Sharepoint, DatabaseProject, SetupProject, Extensibility, Setup , TestProject, CodeAnalysis,Help, Windows Mobile , F#

TODO .NET 4 : CodeContracts, Parallel Extensions, (contra)variance, Tuples, SortedSet si altele

Daca vreti sa contribuiti (cod + text) , va rog sa imi spuneti (email )!

.NET | c#
Monday, May 03, 2010 2:59:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, April 26, 2010


Windows Mobile

O fie in curind lansarea Visual Studio 2010 in Romania si m-am gindit sa scriu un mini-e-book despre ce poti face cu Visual Studio 2010. La ce ar fi bun ? Pai – daca te intereseaza programarea pe WindowsMobile sa stii de un de sa o apuci.

L-am rugat pe Marius Istudor sa participe la acest proiect pentru WindowsMobile 6.5. El a facut scris documentul pe care il vedeti si aplicatia in VS2008 – si , din pacate, VS2010 nu mai suporta Windows Mobile 6.5 (http://msdn.microsoft.com/en-us/library/sa69he4t%28VS.100%29.aspx)

Ii multumesc si pe aceasta cale pentru munca depusa !

-------------------------

Dezvoltarea de aplicatii cu WindowsMobile

De data asta Ion vine cu o noua cerinta :ar putea face o aplicatie pentru WindowsMobile ? Are un client un telefon cu Windows Mobile si ar fi interesat de aplicatie. Ar putea Popescu sa il ajute ?

Popescu studiaza si , pentru ca subiectul e mai lung, scrie un tutorial intreg despre acest lucru:

Programarea pentru dispozitivile mobile este diferita de programarea desktop sau web. Cand construim o aplicatie care va rula pe un smarptphone, pocket pc sau alt dispozitiv cu Windows Mobile, va trebuie sa luam in considerare mai multe lucruri: bateria (aplicatia nu trebuie sa aiba un impact mare asupra consumului bateriei), procesorul (frecvente mici, care afecteaza ritmul operatiilor sau al interogarilor in baza de date), dimensiunea dispozitivului cu rezolutii diferite ale display-ului, conexiunile la retea, memorie, securitate si altele.

In dezvoltarea aplicatiilor destinate dispozitivelor mobile s-au facut progrese, respectandu-se cerintele programatorilor de a avea framework-uri si aplicatii, acelasi IDE atat pentru dezvoltarea mobila cat si pentru cea desktop, curba de invatare usoara, cunostinte de programare ce pot fi folosite in ambele tipuri de programare.

Windows Mobile este versiunea Compact Edition, pentru dispozitivele mobile, a sistemului de operare Windows.

Windows Mobile prezinta ca avantaje, capacitatea extraordinara pentru multi-tasking, alocand automat memorie in functie de necesitatile fiecarei aplicatii, sincronizarea cu un sistem desktop/laptop, interfata intuitiva, mai ales pentru utilizatorii Windows.

O aplicatie Windows Mobile se poate dezvolta in cod nativ (Visual C++), in managed code si in mod server-site (aplicatii gazduite de browser).

Microsoft are o platforma mobila puternica, cu un runtime puternic in .Net Compact Framework, instrumente de dezvoltare puternice ca Visual Studio si un suport pe masura in ceea ce priveste comunitatea programatorilor de Windows Mobile.

Ultima versiune de .Net Compact Framework este 3.5, pe baza careia vom dezvolta aplicatia noastra. Microsoft recomdanda folosirea acestei ultimei versiuni, dar alegerea ramane la atitudinea programatorului (cui se adreseaza aplicatia, de ce particularitati are nevoie in dezvoltarea). Versiunea 2.0 a .Net Compact Framework ruleaza pe foarte multe dispozitve actuale, dar totusi ultima versiune aduce foarte multe lucruri noi in aceasta ramura a programarii, printre care Language Integrated Query, Windows Communication Foundation.

Cerinte pentru dezvoltarea in Windows Mobile

Sistemele de operare:

Windows XP/Windows Server 2003 + ActiveSync (pentru sincronizarea desktop/laptop – dispozitiv mobil)

Windows Vista/Windows 7/Windows Server 2008 + Windows Mobile Device Center (pentru sincronizarea desktop/laptop – dispozitiv mobil)

Instrumente despre dezvoltare

Pentru dezvoltarea unei aplicatii Windows Mobile 6.5, avem nevoie de urmatoarele instrumente:

1. IDE (Integrated Development Environment)

Visual Studio 2008 Professional +.Net Compact Framework 3.5

Visual Studio 2005 Standard + .Net Compact Framework 2

Se recomanda ca acestea sa aiba instalat ultimul Service Pack.

Editiile Express ale Visual Studio nu suporta dezvoltarea proiectelor pentru dispozitive mobile.

2. SDK (Software Development Kits)

Windows Mobile 6 Standard SDK Refresh – contine librarii, documentatie, exemple si coduri sursa pentru dezvoltarea aplicatiilor Windows Mobile 6.

Windows Mobile 6 Professional SDK Refresh – contine in plus,

Se recomanda dezinstalarea versiunilor anterioare de SDK.

Cele doua tipuri de SDK se pot instala simultan.

3. DTK (Developer Tool Kit)

Windows Mobile 6.5 Developer Tool Kit 6.5 - include emulatoarea, API-uri pentru dezvoltarea touchscreen, coduri sursa, disponibile pentru Windows Mobile 6.5.

4. Windows Mobile 6.1 Emulator Images (optional)

Windows Mobile 6.1 Emulator Images – consta intr-un pachet de emulatoare care poate fi folosit cu Visual Studio/sau nu, pentru testarea aplicatiilor. Avem nevoie de emulatoare pentru a suplini lipsa mai multor tipuri de dispozitive si pentru a testa aplicatia noastra in diferite cazuri.

Avand toate instrumentele pregatite si instalate, vom incepe construirea unei aplicatii mobile.

Dezvoltarea unui program Windows Mobile 6.5

Vom crea o aplicatie Windows Mobile 6.5, bazata pe Windows Mobile Standard SDK, adresata dispozitivelor fara touchscreen, care va consta in adunarea a doua numere. Simplu, nu?

Deschidem Visual Studio 2008.

File – New Project

In aceasta prima fereastra, in partea stanga, vom selecta mai intai limbajul de programare, in cazul nostru, Visual C#.

Alegem un proiect de tip SmartDevice, iar in partea dreapta a ferestrei va aparea sablonul (template) corespunzator instalat in Visual Studio 2008 – Smart Device Project.

De mentionat ca un proiect de tip SmartDevice se poate realiza si in limbajul Visual Basic sau Visual C++ (cod nativ – pentru aplicatii simple, foarte performante, care necesita in general accesarea platformei hardware).

clip_image002

Nota: De obicei, cand contruim aplicatii cu Visual Studio 2008, selectam versiunea de .Net Framework pe care o vom folosi. In cazul dezvoltarii unei aplicatii Windows Mobile, acest pas nu are nici o importanta, pentru ca acest tip de aplicatie va folosi .Net Compact Framework, a carei versiune o vom selecta in fereastra urmatoare. Deci, nu ne va interesa selectarea unei anumite versiuni de .Net Framework.

Apasam butonul OK pentru a continua crearea proiectului.

Fereastra urmatoare ne va permite sa finalizam crearea proiectului nostru, prin selectarea mai multor optiuni:

Platforma pe care vom construi aplicatia: Windows Mobile 6 Standard SDK

Versiunea de .Net Compact Framework: 3.5

Vom selecta sablonul pentru Device Application, pentru crearea unei aplicatii de tip forms.

In partea de jos a ferestrei, observati un link catre site-ul Microsoft, de unde puteti descarca toate instrumentele necesare dezvoltarii aplicatiilor Windows Mobile.

clip_image004

Apasam OK si vom termina etapa de configurare a proiectului, urmand sa construim efectiv aplicatia.

Asa va arata forma, cu “skinul” specific unei aplicatii standard:

clip_image005

Daca sunteti familiarizati cu mediul Visual Studio 2008, nu veti observa mari diferente. In partea stanga se afla lista controalelor disponibile (Toolbox), in partea dreapta, Solution Explorer, unde se afla fisierele proiectului. In cazul in care se doreste schimbarea platformei pentru care se dezvolta aplicatia, avem la click dreapta pe proiect optiunea Change Target Platform…

Putem “scapa” de skin, selectand optiunea de la click dreapta Show Skin.

Apelam fereastra de proprietati a formei. Modificam proprietatea Text: Compute Application si putem schimba skin-ul prin selectarea Form Factor.

Controalele disponibile sunt mai putine decat la Windows Forms, dar le putem gasi pe cele mai des folosite. Se pot deriva si crea controale “custom” in aplicatie. Clasele din System.Windows.Forms au fost optimizate pentru resursele unui dispozitiv.

Pentru aplicatia noastra, vom avea nevoie de trei label-uri si doua textbox-uri. De aceste controal, putem dispune prin simplu “drag and drop” din Toolbox.

Putem folosi aceleasi instrumente de aliniere a controalelor din bara de instrumente Layout a Visual Studio.

Primul TextBox corespunzator primului numar, il vom numi txtFirst, pe cel de-al doilea, evident, txtSecond.

Nu trebuie sa ne facem griji pentru latimea celor doua texbox-uri. Le putem seta in asa fel incat, sa fie egale cu latimea maxima a display-ului dispozitivului.

Click dreapta: View Code pentru a naviga in codul din spatele formei (code behind). In constructorul clasei, vom apela metoda ControlSettings, ale carei instructiuni, sunt prezentate mai jos:

private void ControlSettings()

{

//seteaza culoarea fundalului pentru aceasta forma

this.BackColor = Color.Lime;

//seteaza latimea, culoarea fundalului si culoarea textului pentru primul textbox

txtFirst.Width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;

txtFirst.BackColor = Color.Blue;

txtFirst.ForeColor = Color.White;

//seteaza latimea, culoarea fundalului si culoarea textului pentru primul textbox

txtSecond.Width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;

txtSecond.BackColor = Color.Blue;

txtSecond.ForeColor = Color.White;

//eticheta nu va avea text

lblTotal.Text = string.Empty;

}

Pe butoanele principale ale dispozitivului, cele doua softKey-uri (left si right), le vom denumi si vom stabili ca la apasarea lor, fiecare sa apeleze o anumita functie. (le vom crea un handler)

Click pe SoftKey-ul din stanga, iar in fereastra de proprietati (care poate fi apelata cu F4) modificam proprietatea Text si vom adauga Calculeaza. Dublu click pentru crearea unui handler pentru acest buton.

private void menuItem1_Click(object sender, EventArgs e)

{

//daca se returneaza true

if (Validate())

{

//calculeaza

Compute();

//blocheaza controalele dupa calcul

LockControls();

};

}

In acest handler, vom apela o functie de validare a texboxurilor (ambele sa fie completate si sa contina numere). Ea va returna true daca utilizatorul este cuminte J (va introduce in ambele textbox-uri cifre), si va returna false, altfel.

private bool Validate()

{

//verificam daca in ambele textbox-uri au fost introduse caractere

if (txtFirst.Text.Length == 0 || txtSecond.Text.Length == 0)

{

MessageBox.Show("Check if the textboxes are filled in!");

return false;

}

else

{

try

{

first = Double.Parse(txtFirst.Text);

}

//prindem exceptia pentru format invalid – non-numeric

catch

{

MessageBox.Show("Invalid number!");

return false;

}

try

{

second = Double.Parse(txtSecond.Text);

}

//prindem exceptia pentru format invalid – non-numeric

catch

{

MessageBox.Show("Invalid number");

return false;

}

//toate validarile au fost trecute cu succes

return true;

}

}

first si second sunt variabile globale, declarate la inceputul programului:

//variabile globale

private double first = 0;

private double second = 0;

Metoda Compute va returna rezultatul adunarii celor doua numere, convertit in string.

//calculeaza cele doua numere si converteste rezultatul in string

private void Compute()

{

lblTotal.Text = "Sum: " + (first + second);

}

Dupa apelul functiei Compute, se va apela si functia LockControls.

Metoda LockControls va bloca cele doua textbox-uri si butonul corespunzator softkey-ului din stanga, pentru a preveni introducerea altor numere pana la un calcul nou.

private void LockControls()

{

//blocheaza primul element al meniului

mainMenu1.MenuItems[0].Enabled = false;

//blocheaza textbox-urile

txtFirst.Enabled = false;

txtSecond.Enabled = false;

}

In momentul de fata, daca am parcurs tot acest cod, in aplicatie va fi afisata suma celor doua numere .

Trecem la softkey-ul din dreapta, caruia ii modificam proprietatea Text (“Options”) si ii mai adaugam inca doua elemente: Recompute si Exit.

In handler-ul pentru Recompute vom apela functia UnlockControls, care va debloca textbox-urile si butonul Compute pentru a putea inita un alt calcul.

private void UnlockControls()

{

//deblocheaza controalele

mainMenu1.MenuItems[0].Enabled = true;

txtFirst.Enabled = true;

txtSecond.Enabled = true;

//sterge textul din textbox-uri

txtFirst.Text = string.Empty;

txtSecond.Text = string.Empty;

//seteaza focusul pe primul textbox

txtFirst.Focus();

}

Handler-ul butonului Exit va inchide aplicatia.

private void menuItem3_Click(object sender, EventArgs e)

{

//inchide aplicatia

Application.Exit();

}

Dupa ce am terminat, apasam CTRL-SHIFT-B (pentru compilare) si, daca nu avem erori, putem apasa F5 pentru rularea aplicatiei. Imediat, va aparea o fereastra in care sunt disponibile emulatoarele catre care putem face “deploy” aplicatiei.

Selectam unul din emulatoarele unui dispozitiv 6.5. Personal, voi selecta USA Windows Mobile 6.5 Standard Landscape QVGA Emulator.

Mesajul din partea de jos a ferestrei Show me this dialog each time I deploy the application este folositor daca dorim ca aceasta fereastra sa (nu) apara la fiecare rulare a aplicatiei.

clip_image006

Nota: In cazul in care nu se gasesc in lista Emulatoarele pentru Windows Mobile 6.5, asigurati-va ca ati instalat Windows Mobile 6.5 Developer Tool Kit.

Vom continua apasand Deploy.

Actiunea de “deployment” va dura mai mult prima data, pentru ca acesta va include si sistemul de operare, nu doar aplicatia noastra.

Dupa terminarea actiunii de deployment, pe ecran, va rula aplicatia noastra:

clip_image007

Navigarea prin aplicatie se face cu ajutorul butoanelor.

Se introduc de la tastatura doua cifre si se apasa butonul Compute pentru afisarea sumei lor.

Putem testa aplicatia noastra, in diferite ipostaze., configurand emulatorul. Apasam butonul Device Options :

clip_image008

Apare fereastra Options, unde vom selecta emulatorul caruia ii vom modifica proprietatile:

clip_image010

clip_image011

Selectam Emulator Options.

clip_image012

In aceasta fereastra, navigand prin meniul cu tab-uri, putem configura emulatorul pentru situatiile in care vrem ca acesta sa aiba un folder de pe calculatorul nostru (se va comporta ca un “storage card” in emulator). De asemenea, se poate testam aplicatia pe anumite dimensiuni ale display-ului(DISPLAY), conectarea la retea(NETWORK), nivelul baterie scazut(PERIPHERALS), etc.

Windows Mobile este un sistem de operare foarte puternic, adresat unui numar mare si variat de dispozitive, cu o multitudine de aplicatii compatibile (windows market place).

Puteti downloada proiectul de la adresa

http://serviciipeweb.ro/iafblog/content/binary/tutorialWinMobile6.rar

.NET | WindowsMobile
Monday, April 26, 2010 2:47:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Thursday, April 22, 2010


Prezentare ASP.NET MVC 2 si scurt.ro

Daca va pasioneaza ASP.NET MVC 2, atunci va invit sa veniti simbata, 24 aprilie 2010, la Cladirea City Gate, sala de conferinte Romulus si Remus, de la ora 9:30. Voi prezenta ASP.NET MVC 2.0 si citeva lucruri care o sa va faca munca mai usoara ca developer – nu neaparat de MVC ... Totul va fi cu aplicatie practica la www.scurt.ro.

Mai sunt si alte prezentari – cititi aici http://www.codecamp.ro/post/2010/04/09/Codecamp-la-Bucuresti.aspx

Va astept!

.NET | prezentare
Thursday, April 22, 2010 8:29:38 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, February 08, 2010


Salvarea setarilor in .NET

Discutie :

setari globale (write once, read more). De obicei stocate in

Path.GetDirectoryName( Assembly.GetEntryAssembly().GetName().CodeBase))

setari de user (write –read). De obicei stocate in

Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)

Posibilitatea 1 : salvarea in settings

User settings ,application settings

Posibilitatea 2 : salvarea in registry

HKCU, HKLM

Posibilitatea 3 : salvarea in fisiere de configurare

· Connectionstrings

· appSettings

· config class

Posibilitatea 4 : clase serializabile ( de ex, in XML)

Se pune problema unde se serializeaza : hard, baza de date.

Posibilitatea 5 : fisiere Ini

http://jachman.wordpress.com/2006/09/11/how-to-access-ini-files-in-c-net/

http://www.codeproject.com/KB/cross-platform/INIFile.aspx

Posibilitatea 6, Baza de date

Puteti crea o tabela cu 3 coloane : Obiect,Nume,Valoare. Acestati cu EF, L2S , NHibernate sau orice altceva.

Concluzie :

Salvarea setarilor nu e un lucru greu de facut. Problema este unde se salveaza si de catre cine poate fi accesata informatia (administrator sau utilizator obisnuit).

Downloadati codul

Tutoriale video aici

.NET | c# | tutoriale
Monday, February 08, 2010 10:15:52 PM (GMT Standard Time, UTC+00:00)  #    Comments [2]  |  Trackback




Cum sa obtii salvezi setarile

Doua noi tutoriale video despre a salva setarile cu o clasa ce poate fi serializata in fisierul de configuratie si inca unul despre salvarea in registry

.NET | c# | youtube
Monday, February 08, 2010 2:46:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, January 25, 2010


Ajutor la dezvoltarea unei aplicatii

Aplicatia este www.scurt.ro si o gasiti la adresa www.scurt.ro. Este o aplicatie de shortening service ( tinyurl si bit.ly fiind unele cunoscute deja).

Documentatia aplicatiei o gasiti la adresa http://www.scurt.ro/Home/About .

Mai intii , ce vreau sa fac cu aceasta aplicatie: Vreau sa arat ca programarea este doar baza piramidei. Si ca munca pentru o aplicatie simpla este destul de mare, in plus mai trebuie tot felul de persoane  - testare,raportare, administrator de BD, SEO specialist, marketing, vinzari si altii…

Aplicatia mai are citeva chestii de facut ( de ex., paginile pentru utilizatorii inregistrati, logare,erori , add-on de IE si Firefox, SEO, etc- le gasiti in documentul http://www.scurt.ro/Docs/aplicatia%20scurt.docx )

Pentru cei care ma ajuta nu pot sa le promit nimic – decit ca vor fi mentionati printre autori –si vor avea link pus pe o pagina care trebuie definita.

Cine vrea sa ma ajute, va rog sa cititi documentul, downloadati sursele – si vorbim pe email!

Multumesc,

Andrei

.NET | ASP.NET | Asp.NET MVC | c# | tutoriale
Monday, January 25, 2010 3:50:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [1]  |  Trackback


Friday, November 13, 2009


Remote Debugging cu Visual studio

Acesta este un Guest Post de Pascanu Alexandru si a fost inspirata de cartea de pe amazon -  Professional ASP.NET 2.0

Remote debugging e foarte simplu de realizat incepand de la VS 2005 singurele probleme sunt cele de securitate in sensul ca trebuie sa ai credentialele corespunzatoare pe ambele masini (masina client pe care e VS-ul si masina server remote pe care e aplicatia la care vrem sa-i facem debugging).remote debuger se gaseste la C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE eu avand instalat vs 2008 aici .

Am facut acest folder share cu permisiuni de read pt everyone –guest veti vedea mai departe de ce !

Pentru a face remote debugging trebuie setate masina remote pentru aceasta operatiune,in loc de a face niste setari de system complicate si avansate ,tot ce trebuie facut e sa lansam aplicatia msvsmon.exe din shareul creat mai sus –asta de pe masina remote normal.

Se pot depana procese remote ce ruleaza sub contul de user care a lansat Visual studio ,asta fara a da alte permisuni in prealabil .Daca de exemplu trebuie sa se faca debug pe un process care ruleaza sub alt cont de utilizator decat contul care a initiat debuggingul remote,de exemplu un process aspnet,atunci trebuie avute dreturi de administrator pe masina remote-ma refer la contul ce initiaza debuggingul.

Cel mai important lucru cand se face remote debugging e urmatorul:Userul sub care ruleaza Visual studio trebuie mapat cumva catre un cont de utilizator de pe masina remote ce ruleaza msvsmon.exe si viceversa.Cel mai usor se poate face asta creand un cont de user local pe ambele masini cu acelasi username si password.

Daca masinile sunt in acelasi domeniu cel mai simplu e sa se lanseze aplicatiile msvsmon.exe si Visual Studio sub acelasi Domain Account,daca sunt in domenii/workgroupuri diferite solutia e cu acelasi local account.

O observatie merita facuta aici:Pentru masinile windows xp aflate intr-un workgroup politica de securitate Network Acces:Shared and security model for local Accounts afecteaza remote debugging daca e setata guest only,trebuie aleaza optiunea cealalata classic.Acest lucru nu e o problema pt masinile winxp sau win2003 logate intr-un domeniu NT

Debuggingul Remote pe o masina Windows Xp cu sp2

Trebuie sa ne asiguram ca portul TCp 80 e deschis ,asta daca dorim sa depanam o aplicatie aspnet,pentru ca iis si aspnet sa comunice cu masina remote .se recomanda sa tinem limitate aria de unde poate fi facut remote debugging adica local subnet in locul accesarii remote debugging de pe net.”Under the hood” procesul de remote debugging foloseste dcom mai exact se stabileste o conexiune dcom intre client (Visual Studio) si server adica aplicatia msvsmon.exe deci porturile tcp 135 si udp 4500 trebuie sa fie deschise ,dar dupa cum v-am zis se ocupa msvsmon de configurarea masinii,lucrurile astea trebuie avute in vedere daca facem remote debugging de pe internet printr-un vpn tunel ipsec de exemplu si atunci se complica un pic lucrurile.

Un ultim lucru de verificat este ca msvsmon.exe sa fie in lista de exceptii a firewall de xp.Inca odata subliniez nu e recomdat ca sa lasam sesiunea de debugging adica masina pt remote debugging lumii din afara internetului.remote debugging in sine e ultima solutie –in cazul in care un bug nu poate fi repprodus pe masina de test/development si trebuie sa se faca pe masina de productie de deployment.

O sa prezint mai jos urmatorul caz pe care l-am reprodus la mine:

Visual Studio ruleaza pe o masina din domeniul firmei iar msvsmon.exe masina pe care fac remote debugging ruleaza pe o masina virtuala de windows 7 cu un worckgroup al ei:

Primul pas ma loghez pe statia mea windows 7 (vm-ul pe care fac debugging) cu userul local Alex –user cu care voi rula visual studio atentie trebuie sa fie acelasi pt ca unul e in worckgroup altul domeniu.

Pas2 accesez aplicatia msvsmon.exe din shareul Remote Debugging despre care am vorbit mai sus

clip_image002

Pas 3Din acest share lansez aplicatia msvsmon.exe:

clip_image004

Pas4 Rulez Visual studio ca si userul local Alex –user sub care ruleaza msvsmon.exe remote-pt asta dau click drepta pe Vs run as si aleg useru alex.Pe vm pornesc aplicatia dot net la care se vrea depanarea:

clip_image006

Pas 5 Din vs2008 ma atasez remote la procesul pe care vreau sa-l depanaez in cazul meu Aplicatia Adm_client.exe in cazul in care conexiunea s-a realizat cu success in msvsmon o sa afisat userul alex-pc cu statusul connected ca in figura:

clip_image008

Pas 6 Nu-mi ramane decat sa pun un break point in locul in care vreau depanarea in cazul meu am pus la lina catch cand conexiunea nu se poate realize sis a incerc din aplciatia remote sa execut operatiunea de logare.Se observa ca debuggerul se lanseaza in locul in care am pus breakpoint:

clip_image010

Cam asta ar fi tot,sper ca m-am facut destul de explicit si ca o sa foloseasca cuiva vreodata acest articol.

 

Acesta este un Guest Post de Pascanu Alexandru si a fost inspirata de cartea de pe amazon -  Professional ASP.NET 2.0

.NET | debug | guest post
Friday, November 13, 2009 10:22:18 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, November 09, 2009


HTML Agility Pack

Cum fac simplu citirea de pagini de pe Web ? Prima varianta este sa incercati cu WebRequest , http://msdn.microsoft.com/en-us/library/system.net.webrequest.aspx . Dar ar trebui sa parsati HTML-ul care NU este XHTML … si imediat va ginditi ca mai sunt sute altii care au aceeasi problema. Asa ca am gasit HTML Agility Pack , http://www.codeplex.com/htmlagilitypack , care stie sa transforme un HTML in XHTML.

Codul pentru incarcarea unei pagini e ridicol de simplu :

HtmlWeb hw = new HtmlWeb();
hw.AutoDetectEncoding = true;
HtmlDocument  doc = hw.Load(Url);
HtmlNode NodeRoot = doc.DocumentNode;

Si de la NodeRoot puteti incepe XPATH cu SelectNodes

.NET | HTML Agility Pack | tools
Monday, November 09, 2009 3:10:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, October 26, 2009


JetBrains dot trace 3.1

Am avut ocazia sa am pe mina Dot Trace de la Jet Brains. Si l-am incercat pe o aplicatie Windows, dar unde si-a aratat puterea a fost in aplicatii Web.

Ca sa vezi ce iti ia cel mai mult timp din aplicatie ai putea sa faci asa : dupa ce ai facut un snapshot, apesi pe plain view, dupa care apesi pe filter. Frumos din partea lui ca vine cu citeva definitii deja existente pentru tool-uri pe care nu vrei sa le vezi la inceput :

121106_Filters_active

 

Dar poti sa mai adaugi si tu altele – daca vezi ca obtii in fata alte chestii(MS, log4net) de care vrei sa scapi si esti 99% sigur ca sunt optimizate la greu.

In fine, dupa ce dai OK, poti incepe sa inspectezi codul. Asa am vazut ca, pentru o pagina in care ar fi trebuit chemat “get_LastStep”  de 9 ori , se chema de 18 ori cu un timp total de 11 ms. Concluzia : se impune un cache – macar primitiv!

Ca puncte tari : are export in XML. Dar tare m-ar fi bucurat un export in Excel – sa pot sa fac eu sortare /filtrare si alte chestii…

De avut NEAPARAT!

 

De folosit oricind dupa terminarea unui proiect(atentie : aici se vede cit de bune au fost testele!)

.NET | c# | dot trace | jetbrains | tools
Monday, October 26, 2009 2:19:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, September 28, 2009


ASPOSE si Documentele Word

Pentru infovalutar (mai exact, pentru mine …) am vrut sa preiau licitatiile de la banci.

Pentru rezultatul final, vezi http://infovalutar.ro/licitatie

Dar sa vedem care a fost povestea  :am inceput cu preluarea paginilor HTML . Incepusem cu  HttpWebRequest - dar am descoperit la timp HtmlAgilityPack si am ramas credincios lui.

Acum, dupa preluarea paginilor HTML( de ex., http://www.banca-romaneasca.ro/main.php?did=527&code=executare+silita) a fost de ajuns un XPath + expresie regulata de parsare a text-ului din interior.

Ce mi-a produs batai de cap a fost http://vanzari.leumi.ro/bunuri_imobile.html – aveau bunurile in document Word! Ori, ca sa ii ceri celui de la Hosting sa instaleze Word-ul ca sa il instantiezi tu in ASP.NET e aproape imposibil!

Solutia : ASPOSE.WORDS  - citeste documente dintre cele mai diverse si scoate un TXT superb – si asta, fara sa aiba nevoie de WORD instalat(se prea poate sa fi omorit muste cu tunul …)

Ca folosire, trebuia sa ii dau un Stream – dar cind am incercat sa ii dau stream-ul de document, mi-a zis ca nu suporta Seek. Asa incit am rezolvat cu un MemoryStream :

public string LeumiData(string URL)
        {

            byte[] buffer = new byte[1024*1024*4];

            HttpWebRequest hwr = WebRequest.Create(URL) as HttpWebRequest;
            using (WebResponse response = hwr.GetResponse())
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        int count = 0;
                        do
                        {
                            count = responseStream.Read(buffer, 0, buffer.Length);
                            memoryStream.Write(buffer, 0, count);

                        } while (count != 0);

//ASPOSE
                        Document d = new Document(memoryStream);
                        return d.ToTxt();

                    }
                }
            }

        }

Pot sa spun ca ASPOSE, daca vreti manipulare de documente, face toti banii!

.NET | ASP.NET | ASPOSE | programare | tools
Monday, September 28, 2009 2:12:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback




Structure Map

La ce foloseste StructureMap ? Raspunsul pe scurt  : este un tool simplu de DI

Raspunsul pe lung : in postul precedent, vroiam sa testez un export de fisiere fara sa ating BD.

Initial, codul arata cam asa :

public ActionResult ExportDate(string id)
{

DateExport fe = new DateExport();
fe.id = id;

export exp = new export(Server.MapPath("~/bin/Templates"));

FileContentResult fcr = new FileContentResult(exp.Export(fe), "application/ms-word");
fcr.FileDownloadName = fe.Number + ".doc";

return fcr;

}

unde variabila fe din

DateExport fe = new DateExport();

atingea BD in momentul in care cineva ii cerea niste date.

Vroiam sa o inlocuiesc cu o variabila ce trimite null ca date si apoi cu variabila care trimite niste date fake.

Ca sa fac acest lucru, am extras metodele care ma interesau din DateExport, am facut o interfata din ele IDateExport, am inlocuit vparametrul din functia export ce cerea un DateExport cu IDateExport si am folosit StructureMap :

In global.asax am definit cererea default :

ObjectFactory.Initialize(x =>
            {
                x.ForRequestedType<IDateExport>().TheDefault.Is.ConstructedBy(() => new DateExport(HttpContext.Current.User.Identity.Name));
            });

si apoi in metoda am inlocuit new cu ObjectFactory :

public ActionResult ExportDate(string id)
{

IDateExport fe = ObjectFactory.GetInstance<IDateExport>();
fe.id = id;

export exp = new export(Server.MapPath("~/bin/Templates"));

FileContentResult fcr = new FileContentResult(exp.Export(fe), "application/ms-word");
fcr.FileDownloadName = fe.Number + ".doc";

return fcr;

}

Acum testul automat a devenit floare la ureche – sa zicem ca vreau ca metodele din IDataExport sa nu aduca nimic –si sa testez acest lucru . Creez o clasa DataExportNotFind, implementez IDataExport ca sa nu aduca nimic si scriu in test :

ObjectFactory.Initialize(x =>
{
    x.ForRequestedType<IDataExport>().TheDefaultIsConcreteType<DataExportNotFind>();
});

 

Si asta e tot!

As vrea sa pun accent pe faptul ca , desi testez rapid pe masina proprie facind un fake la BD, totusi, la integrare, ar trebui sa aveti teste cu BLL / UI care sa testeze NEAPARAT cu BD …

.NET | Dependency Injection | Structure Map | testare | tools
Monday, September 28, 2009 2:03:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, September 21, 2009


Rhino Mock

Destul de tirziu mi-am dat seama de beneficiile aduse de un Mock – dar mai bine mai tirziu decit niciodata …

Ma gindeam ca niciodata nu o sa il folosesc – ca ajunge sa verific BLL cu unit test(NUNIT/VS Test) , site-ul Web cu NUnit ASP/WATI(N|R) / Selenium , Windows Forms cu NUnitForms si nu o sa am nevoie de Mock.

Adevarul este ca da, nu as avea nevoie de Mock … decit daca as vrea sa verific mai repede unele date, fara sa ating BD.De exemplu, pot sa verific controller-ele fara sa am nevoie sa instantiez HttpContext si BD. Sa zicem ca am un controller care are o actiune ce doar exporta un fisier Word– bazat pe un template. Codul din fisier  arata cam asa :

public ActionResult ExportDate(string id)
{

IDateExport fe = ObjectFactory.GetInstance<IDateExport>();
fe.id = id;

export exp = new export(Server.MapPath("~/bin/Templates"));

FileContentResult fcr = new FileContentResult(exp.Export(fe), "application/ms-word");
fcr.FileDownloadName = fe.Number + ".doc";

return fcr;

}

Daca as vrea sa verific rapid metoda aceasta ar trebui sa nu ating baza de date si sa am pun un rezultat in loc de Server.MapPath ?

Se vede clar ca deja folosesc StructureMap, deci nu ar fi o problema cu gasitul a niste date fake. Dar pentru Server.MapPath intervine stralucit Mock.

Am preluat de la Hanselmann MVC Mock Helpers ,iar codul de test arata cam asa :

 

exportController i = new exportController();
MockRepository mocks = new MockRepository();
using (mocks.Record())
{
    //MvcMockHelpers.SetFakeControllerContext(mocks, i);
    mocks.SetFakeControllerContext(i);
   SetupResult.For(i.ControllerContext.HttpContext.Server.MapPath(null)).IgnoreArguments().Return(@"c:\programs\templates");      // cod pentru chemarea Server.MapPath          
    mocks.ReplayAll();
}
using (mocks.Playback())
{
    ObjectFactory.Initialize(x =>
    {
        x.ForRequestedType<IExport>().TheDefaultIsConcreteType<FactFind>();// FactFind nu atinge BD
    });
    FileContentResult fcr = i.exportdate("865", "A") as FileContentResult;
    fcr.ShouldNotBeNull();
    fcr.FileContents.Length.ShouldBeGreaterThan(0);//TODO : Verifica si continutul
}

.NET | ASP.NET | Asp.NET MVC | Rhino Mock | testare | tools
Monday, September 21, 2009 1:49:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1]  |  Trackback


Monday, September 14, 2009


Tips and trick cu Entity Framework

 

1. Cum obtineti Connection String curat din Entity Framework Connection String

Sa zicem ca aveti definit connection string pentru EF in (web|app).config , ceva de genul :

<connectionStrings>
      <add name="iERPEntities" connectionString="metadata=res://*/ERP.csdl|res://*/ERP.ssdl|res://*/ERP.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=PC;Initial Catalog=ERP;Persist Security Info=True;User ID=x;Password=xy;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

 

Si vreti sa preluati rezultatele de la o procedura stocata sau doar sa o executati, fara sa va mai chinuiti sa o treceti prin EF (mai mare deranjul). In consecinta va trebuie connection string-ul.

2. Cum faci Union – sau Join -  intre 2 IQueryable – ca sa iti dea macar una din ele, daca cealalta e null ?

3. Daca stii cheia unui obiect  -de obicei long ID  - cum obtii obiectul ?

4. Cum poti vedea ce genereaza, ca string sql, entitycontext – fara sa stai cu profiler-ul pe Sql Server ?

5. Daca vreti sa faceti o tabela pentru ca sa accesati/modificati continutul cu EF, ce este BestPractices de definit la ea ?

6. Cum validati un obiect in EF inainte de a salva ?

Va las sa va bateti capul! Raspunsurile mai jos…

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Rezolvarea 1.

string sqlc = "";
            using (ERPEntities e = new ERPEntities("name=iERPEntities"))
            {
                EntityConnection ec = e.Connection as EntityConnection;
                sqlc = ec.StoreConnection.ConnectionString;
            }

De ce e.Connection nu e direct EntityConnection si trebuie cast-uit, depaseste imaginatia mea …

Rezolvarea 2.

public static IQueryable<T> coalesceIntersect<T>(IQueryable<T> x, IQueryable<T> y)
           where T : class
        {

            if (x == null)
                return y;

            if (y == null)
                return x;

            return Queryable.Intersect<T>(x, y);

        }

Rezolvarea 3.

/// <summary>
        /// see also http://msdn.microsoft.com/en-us/library/bb896251.aspx
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="o"></param>
        /// <param name="ID"></param>
        /// <param name="Include"></param>
        /// <returns></returns>
        public static T FindFromPrimaryKey<T>(this ObjectQuery<T> o, long ID, params string[] Include)
            where T : EntityObject
        {
            Type t = typeof(T);
            string FullPath = t.FullName;
            if (!KeysForObject.ContainsKey(FullPath))
            {
                lock (KeysForObject)
                {
                    if (!KeysForObject.ContainsKey(FullPath))
                    {
                        foreach(PropertyInfo pi in t.GetProperties())
                        {
                            object[] attr = pi.GetCustomAttributes(typeof(EdmScalarPropertyAttribute),false);
                            if(attr != null && attr.Length ==1)
                            {
                                EdmScalarPropertyAttribute a=attr[0] as EdmScalarPropertyAttribute;
                                if(a.EntityKeyProperty)
                                {
                                    KeysForObject.Add(FullPath,pi.Name);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
           

if(Include != null && Include.Length > 0)
            {
                foreach(string s in Include)
                {
                    o=o.Include(s);
                }
            }
return o.Where("it." + KeysForObject[FullPath] + " = " + ID).FirstOrDefault();

Rezolvarea 4.

http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=1555711&SiteID=1

Rezolvarea 5.

Definiti neaparat Primary Key ( eu de obicei pun un bigint identity )

Rezolvarea 6.

Vedeti http://msdn.microsoft.com/en-us/library/cc716714.aspx

Adaugati o clasa partiala de tipul entitatii in care puneti partial pe OnContextCreated ca sa interceptati SavingChanges

partial class Entities
    {

partial void OnContextCreated()
        {
       

            this.SavingChanges += new EventHandler(Entities_SavingChanges);
        }

}

Eu am facut apoi o interfata IValidate de felul urmator – simplist – :

public enum ISValid
    {
        Yes,
        No,
        SendDataContext
    }
    public interface IValidate
    {
        ISValid IsValidForSaving(ObjectStateEntry ose, out string mesaj);
    }
    public interface IValidateDataContext // daca am nevoie de verificari mai ample cu alt obiect …
    {
        bool IsValidForSavingDataContext(ObjectContext oc, ObjectStateEntry ose, out string mesaj);
    }

Apoi pe SavingChanges :

void Entities_SavingChanges(object sender, EventArgs e)
        {
                     Entities context = sender as Entities;
            foreach (ObjectStateEntry ose in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
            {
                if (ose.Entity == null)
                    continue;
                IValidate iv = ose.Entity as IValidate;
                if (iv != null)

{

string mesaj;
                   switch (iv.IsValidForSaving(ose, out mesaj))
                   {
                       case ISValid.No:
                           throw new NotValidException(ose.Entity.GetType().Name, mesaj);
                       case ISValid.Yes:
                           break;
                       case ISValid.SendDataContext:
                           IValidateDataContext ivDC = ose.Entity as IValidateDataContext;

                           if(!ivDC.IsValidForSavingDataContext(context,ose, out mesaj))
                               throw new NotValidException(ose.Entity.GetType().Name, mesaj);
                           break;
                   }


}

Ok, se putea si mai bine, cu IDataErrorInfo – dar … sa o lasam asa deocamdata

.NET | entity framework | tips
Monday, September 14, 2009 2:01:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, September 07, 2009


Primii 10 pasi cu ASP.NET MVC
  1. Download asp.net mvc 1.0 from http://www.asp.net/mvc/download/
  2. Pentru IIS6 – cititi http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx . Practic mapati toate extensiile (.*) la asp.net si o sa va mearga si pe IIS6.
  3. La Project =>references => System.Web.Mvc => properties => CopyLocal la true – in eventualitatea ca providerul de hosting nu are ASP.NET MVC
  4. Descarcati un template vizual(daca nu sunteti buni la web design!) de lahttp://www.asp.net/mvc/gallery/ si suprascrieti site-ul .
    • Daca va da “The type or namespace name 'Helpers' could not be found (are you missing a using directive or an assembly reference?)” atunci e cazul sa dati “Show all files” si pe urma sa includeti fisierele lipsa . Recompilati. Rulati.Vedeti referintele pentru CSS.
  5. Stabiliti o clasa model pentru Master   - in care puneti cel putin o proprietate User – user-ul curent .  Schimbati inherits la master in “Inherits="System.Web.Mvc.ViewMasterPage<namespace.clasamea>" .Schimbati si in about si in home : return View() in Return view(new clasamodel{});  ; Nu uitati sa schimbati master-ul la error.aspx, pentru ca vrea derivat din System.Web.Mvc.HandleErrorInfo – si sa verificati !
  6. Modificati proiectul sa fie Web ( Project => Properties =>Web => Use Local IIS WebServer si apasati pe CreateVirtualDirectory) . Compilati si rulati. Daca va apare ciudat, refaceti referintele la Css din Views=>Shared>Site Master
  7. Adaugati routedebugger(http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx) si ginditi-va / verificati-va rutele!
  8. MVC Contrib – pentru grid http://mvccontrib.codeplex.com/
  9. adaugati whitespace , output cache – pentru optimizari
  10. Daca vreti sa folositi Handlere de eroare pe Controlere, nu uitati de customErrors la RemoteOnly ( sau On).
  11. Facultativ : Nunit , NBehave, log4net, PostSharp ,log4postsharp, RhinoMocks (nu uitati ca merge doar cu metoda virtuale…), NBuilder , Structure Map , Selenium ,AutoMapper si alte frameworkuri.

Voi ce alte frameworkuri/tools-uri folositi ?

.NET | ASP.NET | Asp.NET MVC
Monday, September 07, 2009 2:06:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  |  Trackback


Monday, August 24, 2009


Issue Tracker

Aveam nevoie de un tracker de issue – pentru ca incepusem sa am prea multe cereri de modificare si nu ma mai descurcam. De fapt, la o a doua vedere, nu erau atit de multe cereri, cit detalii ale lor.

Am cerut pareri pe RONUA – dar ceea ce mi s-a oferit de acolo era pe bani (ma rog, OnTime se pare ca are oferte speciale..). Iar in criza actuala sa cer bani de la servici ca eu nu ma mai descurc suna cam prost…

Dupa ce am citit de mai multe , m-am decis pentru BugTracker.NET. Am avut doua probleme : Integrarea cu Active Directory – din fericire Web.Config este destul de clar scris – si trimiterea emailurilor. Nu vroiam sa configurez SMTP – ci doar sa isi ia setarile din Web.Config de forma:

<system.net>
        <mailSettings>
            <smtp>
                <network host="xxxx" port="25"/>
            </smtp>
        </mailSettings>
    </system.net>

Din nefericire el lucra cu System.Web.Mail – asta pentru ca ,zicea el, noul System.NET.Mail nu suporta SSL.

In fine – nu aveam nevoie de SSL –asa ca am muncit sa il transform – si am modificat pe ici, pe colo, prin partile esentiale email.cs:

/*
Copyright 2002-2008 Corey Trager
Distributed under the terms of the GNU General Public License
*/

using System;
using System.Collections;
using System.IO;
using System.Text;

// disable System.Net.Mail warnings
#pragma warning disable 618

namespace btnet
{

    public class Email {
        ///////////////////////////////////////////////////////////////////////
        public static string send_email( // 5 args
            string to,
            string from,
            string cc,
            string subject,
            string body)
        {
            return send_email(
                to,
                from,
                cc,
                subject,
                body,
                false,
                System.Net.Mail.MailPriority.Normal,
                null,
                false);
        }

        ///////////////////////////////////////////////////////////////////////
        public static string send_email( // 6 args
            string to,
            string from,
            string cc,
            string subject,
            string body,
            bool isbodyhtml)
        {
            return send_email(
                to,
                from,
                cc,
                subject,
                body,
                isbodyhtml,
                System.Net.Mail.MailPriority.Normal,
                null,
                false);
        }

        ///////////////////////////////////////////////////////////////////////
        public static string send_email(
            string to,
            string from,
            string cc,
            string subject,
            string body,
            bool isbodyhtml,
            System.Net.Mail.MailPriority priority,
            int[] attachment_bpids,
            bool return_receipt)
        {
            ArrayList files_to_delete = new ArrayList();
            ArrayList directories_to_delete = new ArrayList();
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(from, to);
            if (!string.IsNullOrEmpty(cc.Trim()))
            {
                msg.CC.Add(cc);
            }
            msg.Subject = subject;
            msg.Priority = priority;

            // This fixes a bug for a couple people, but make it configurable, just in case.
            if (Util.get_setting("BodyEncodingUTF8", "1") == "1")
            {
                msg.BodyEncoding = Encoding.UTF8;
            }

            if (return_receipt)
            {
                msg.Headers.Add("Disposition-Notification-To", from);
            }

            // workaround for a bug I don't understand...
            if (Util.get_setting("SmtpForceReplaceOfBareLineFeeds", "0") == "1")
            {
                body = body.Replace("\n", "\r\n");
            }

            msg.Body = body;
            msg.IsBodyHtml = isbodyhtml;

            if (attachment_bpids != null && attachment_bpids.Length > 0)
            {

                string upload_folder =  btnet.Util.get_upload_folder();

                if (string.IsNullOrEmpty(upload_folder))
                {
                    upload_folder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                    Directory.CreateDirectory(upload_folder);
                    directories_to_delete.Add(upload_folder);
                }

                foreach (int attachment_bpid in attachment_bpids)
                {
                    byte[] buffer = new byte[16 * 1024];
                    string dest_path_and_filename;
                    Bug.BugPostAttachment bpa = Bug.get_bug_post_attachment(attachment_bpid);
                    using (bpa.content)
                    {
                        dest_path_and_filename = Path.Combine(upload_folder, bpa.file);
                        using (FileStream out_stream = new FileStream(
                            dest_path_and_filename,
                            FileMode.CreateNew,
                            FileAccess.Write,
                            FileShare.None))
                        {
                            int bytes_read =  bpa.content.Read(buffer, 0, buffer.Length);
                            while (bytes_read != 0)
                            {
                                out_stream.Write(buffer, 0, bytes_read);

                                bytes_read = bpa.content.Read(buffer, 0, buffer.Length);
                            }
                        }

                    }

                    System.Net.Mail.Attachment mail_attachment = new System.Net.Mail.Attachment(
                        dest_path_and_filename);
                    msg.Attachments.Add(mail_attachment);
                    files_to_delete.Add(dest_path_and_filename);
                }
            }

            try
            {
                // This fixes a bug for some people.  Not sure how it happens....
                msg.Body = msg.Body.Replace(Convert.ToChar(0), ' ').Trim();
                System.Net.Mail.SmtpClient s=new System.Net.Mail.SmtpClient();
                s.Send(msg);

                // We delete late here because testing showed that SmtpMail class
                // got confused when we deleted too soon.
                if (files_to_delete.Count > 0)
                {
                    foreach (string file in files_to_delete)
                    {
                        File.Delete(file);
                    }
                }

                if (directories_to_delete.Count > 0)
                {
                    foreach (string directory in directories_to_delete)
                    {
                        Directory.Delete(directory);
                    }
                }

                return "";
            }
            catch (Exception e)
            {
                Util.write_to_log("There was a problem sending email.   Check settings in Web.config.");
                Util.write_to_log("TO:" + to);
                Util.write_to_log("FROM:" + from);
                Util.write_to_log("SUBJECT:" + subject);
                Util.write_to_log(e.GetBaseException().Message.ToString());
                return (e.GetBaseException().Message);
            }

        }

    } // end Email

} // end namespace

.NET | BugTracker.NET | tools
Monday, August 24, 2009 2:03:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, August 17, 2009


NCover 2.0

Auzisem de NCover – dar nu avusesem posibilitatea sa il pun la lucru.

De ce vroiam sa il folosesc ? Simplu: aveam teste automate (NUNIT) pentru proiect –unele cu Baza de date, altele fara. Ceea ce vroiam sa aflu este cit de mult acopar din codul sursa – adica cit de mult testele sunt complete.

OK – citind putin a inceput sa devina evident cum sa il folosesc – desi are o curba initiala de invatat de vreo 5 minute(nu e evident)

Primul lucru, daca vreti sa il folositi cu NUnit, este sa incercati sa rulati proiectul NUnit din consola, ceva de genul

nunit-console “<fisier.nunit>" 

( daca vreti, puteti continua linia cu  /include=categorii_de_teste )

Daca a rulat OK ( adica fara erori… ) acum putem configura NCover . Porniti NCover Explorer, apasati CTRL+N si o sa vi se deschida o fereastra de comanda in care veti introduce calea catre nunit-console iar la application arguments calea catre fisierul NUnit.

071230_Run NCover_active

Rulati si o sa aveti rapid o evidenta in ce proportie codul din clase s-a executat. In plus va puteti uita direct intr-o metoda sa vedeti care cod s-a executat si care nu ( theme Underline mi se pare cea mai buna)

Generarea rapoartelor e buna – doar ca nu lanseaza fisierul htm generat si trebuie sa il gasiti singuri ( de aceea are “Explore coverage folder”)

Un tool exceptional, ce il puteti rula si din command line . Recomandat cu tarie!

.NET | NCover | nunit | tools
Monday, August 17, 2009 2:01:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  |  Trackback


Monday, August 10, 2009


NBuilder

Ce este NBuilder  ? Un generator automat de obiecte – la care adauga proprietati default.

De ex:

var generator = new UniqueRandomGenerator();
var seq = new SequentialGenerator<int> { Direction = GeneratorDirection.Ascending, Increment = 1};
seq.StartingWith(1);
BuilderSetup.DisablePropertyNamingFor<Linii, int>(x => x.Pret);

Factura oh = Builder<Factura>.CreateNew().Build();
var q = Builder<Linii>.CreateListOfSize(10)
    .WhereAll()
    .Have(x=>x.Qty=generator.Next(1,100))
    .And(x=>x.LineNumber = seq.Generate())               
    .Build();

oh.Linii.AddRange(q);

 

E foarte bun la asta – si l-am folosit atunci cind vroiam generarea de date discrete ca sa le export in Excel…

Ce am invatat de la NBuilder  :

  1. Ca nu am nevoie neaparat de mocking Stubs
  2. Ca nu ar trebui ca proprietatile sa genereze efecte secundare( ca de exemplu calcularea totalului unei facturi nu ar trebui sa faca refresh la linii, chiar daca nu s-a facut incarcarea liniilor)

E free – si f bun la generare. Diferenta de timp intre el si baza de date este de 1088 ms versus 3141 ms. Folositi cu incredere la teste!

.NET | nbuilder | tools
Monday, August 10, 2009 2:00:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, July 27, 2009


PostSharp si Log4PostSharp

Cred ca toata lumea stie la ce e bun Log4Net – este un logger . E foarte bun la log-at mesaje – in principiu cele de eroare – si trimis in cele mai diverse surse – la de fisiere text la console si la BD.

Dar problema este ca as fi vrut ceva sa imi logheze intrarea si iesirea dintr-o metoda, ceva de genul :

public string Arata(Point P, string s){

logger.Debug(“ am intrat cu Point “ + P + “ si string “ + s);

//code

logger.Debug(“ am iesit cu rezultatul “ + ….)
}

La recomandarea lui Dan Bunea, am dat de PostSharp si Log4PostSharp

Dupa ce m-am chinuit sa il fac sa lucreze , iata la ce am ajuns:

1. Un folder lib , in care am pus fisierele :

lib\a.txt
lib\Default.psproj
lib\Log4PostSharp.dll
lib\Log4PostSharp.pdb
lib\Log4PostSharp.psplugin
lib\Log4PostSharp.Weaver.dll
lib\plugins
lib\PostSharp-1.0.targets
lib\PostSharp-1.0.version
lib\PostSharp-AppDomain.config
lib\PostSharp-Library.config
lib\PostSharp-Platform.config
lib\PostSharp.Core.dll
lib\PostSharp.Core.XmlSerializers.dll
lib\PostSharp.exe
lib\PostSharp.exe.config
lib\PostSharp.Laos.dll
lib\PostSharp.Laos.psplugin
lib\PostSharp.Laos.Weaver.dll
lib\PostSharp.MSBuild.dll
lib\PostSharp.Public.dll
lib\PostSharp.targets
lib\plugins\Log4PostSharp.dll
lib\plugins\Log4PostSharp.pdb
lib\plugins\Log4PostSharp.psplugin

2. Project Properties=> Reference Paths=> adaugat folderul lib

3. Un fisier .psproj numit la fel ca proiectul, in care am scris standard

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
    <SearchPath Directory="bin/{$Configuration}"/>
    <SearchPath Directory="{$SearchPath}" />
    <SearchPath Directory="lib" />   
    <Tasks>
        <AutoDetect />
        <Compile TargetFile="{$Output}" IntermediateDirectory="{$IntermediateDirectory}"  CleanIntermediate="false" />
    </Tasks>
</Project>

4. In csproj adaugat cu mina, linga <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

<PropertyGroup>
   <DontImportPostSharp>True</DontImportPostSharp>
   <PostSharpDirectory>lib\</PostSharpDirectory>
   <PostSharpUseCommandLine>True</PostSharpUseCommandLine>
</PropertyGroup>

<Import Project="$(PostSharpDirectory)PostSharp.targets" Condition=" Exists('$(PostSharpDirectory)PostSharp.targets') " />

5. In AssemblyInfo.cs adaugat  (pentru a genera pentru fiecare metoda)

[assembly: Log(AttributeTargetTypes = "*", EntryLevel = LogLevel.Debug,
    EntryText = "Entering method: {signature} with parameters {paramvalues}", ExitText = "exit method {signature} with {returnvalue}",
  ExitLevel = LogLevel.Debug, ExceptionLevel = LogLevel.Error, AttributePriority = 1)]

Asta ca sa genereze un log pentru fiecare metoda …

6. Incepe log4net Adaugat un fisier log4net.config si pus

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo("log4net.config"));

 

GATA! Configurat – si apoi am uitat de el….

Output-ul este ceva de genul :

2009-07-17 22:24:08,541 [TestRunnerThread] DEBUG fisier.cs  Namespace.Clasa [(null)] - Entering method: Void .cctor() with parameters
2009-07-17 22:24:08,729 [TestRunnerThread] DEBUG fisier.cs  Namespace.Clasa [(null)] - exit method Void .cctor() with
2009-07-17 22:24:08,760 [TestRunnerThread] DEBUG fisier.cs  Namespace.Clasa [(null)] - Entering method: Namespace.ClasaList Find(System.String) with parameters "5888"
2009-07-17 22:24:08,760 [TestRunnerThread] DEBUG   Namespace.ClasaList [(null)] - Entering method: Void .ctor() with parameters
2009-07-17 22:24:08,760 [TestRunnerThread] DEBUG   Namespace.ClasaList [(null)] - exit method Void .ctor() with
2009-07-17 22:24:08,760 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - Entering method: Void .cctor() with parameters
2009-07-17 22:24:08,760 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - exit method Void .cctor() with
2009-07-17 22:24:09,166 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - Entering method: Void .ctor() with parameters
2009-07-17 22:24:09,166 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - exit method Void .ctor() with
2009-07-17 22:24:09,198 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - Entering method: System.Data.Linq.Table`1<Namespace.clasa1> get_clasa3() with parameters
2009-07-17 22:24:09,401 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - exit method System.Data.Linq.Table`1<Namespace.clasa1> get_clasa3() with Table(clasa2)
2009-07-17 22:24:11,307 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - Entering method: System.Data.Linq.Table`1<amespace.clasa2> get_clasa4() with parameters
2009-07-17 22:24:11,417 [TestRunnerThread] DEBUG clasa2.cs  namespace.DataContext [(null)] - exit method System.Data.Linq.Table`1<amespace.clasa2> get_clasa4() with Table(clasa2)
2009-07-17 22:24:11,495 [TestRunnerThread] DEBUG fisier.cs  Namespace.Clasa [(null)] - exit method Namespace.ClasaList Find(System.String) with Clasa2List : 0

.NET | Log4Net | Log4PostSharp | PostSharp
Monday, July 27, 2009 12:02:00 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Sunday, July 05, 2009


Business intelligence(cu forecast pe curs Euro) revine

Nu eram deloc multumit de cum facusem predictia de curs valutar – exportam datele din tabela de SqlServer in Excel, pe aceasta analizam “in the cloud” si apoi generam fisierul html cu un macro de Excel …Naspa rau! Normal ca vroiam sa se generewze automat de la datele din tabela – si apoi sa se verse singra intr-o BD.

Asa incit am luat decizia sa studiez un pic cum se face(rezultate aici) –si iata ideile principale:

1. Nu va fie frica sa va creati sursele de date , cuburile si dimensiunile (folositi pentru aceasta VS, nu SSMS – din pacate NU merge in SSMS !). E acelasi lucru ca si cum ati defini o BD normala – si ati lucra cu ea.Dupa ce creeati, va trebui sa ii faceti “Deploy”c a sa o vedeti si in Analysis Services. O sa trec la nivelul urmator (generare automata a BI din cod) mai tirziu.

2.Chiar daca Baza de date principala isi schimba valorile,ca sa isi schimbe si Analysis Services  trebuie sa ii dati “Process” din nou …Neplacut, dar asta e. In mod programatic din C#:

using(Microsoft.AnalysisServices.Server s=new Microsoft.AnalysisServices.Server())
            {
                s.Name = "localhost";
                s.Connect("localhost");
                s.Refresh();
                using(Database d=s.Databases["analtest1"])
                {
                    d.Refresh();
                    d.Process(ProcessType.ProcessFull);
                }
            }

3. Pentru a obtine valorile forecastate, sintaxa este uimitor de asemanatoare cu cea obisnuita din ADO.NET:

using (AdomdConnection con = new AdomdConnection())
            {
                con.ConnectionString = "Data Source=localhost;Catalog=xxx";
                con.Open();
                using (AdomdCommand cmd = new AdomdCommand())
                {
                    cmd.CommandText = "select PredictTimeSeries(Valoare,25) AS Predictie from [Vw Eur]";
                    cmd.CommandType = CommandType.Text;
                    cmd.Connection = con;
                    using (AdomdDataReader dr = cmd.ExecuteReader())
                    {

                        while (dr.Read())
                        {

Totusi, te poti insela rapid:

4. Ca sa obtin tabelul de predictie, a trebuit sa vad in SSMS rezultatul si asa m-am prins ca dr are un singur rind, si acela fiind tot un AdomdDataReader 

while (dr.Read())
                       {
                           using (AdomdDataReader pred = dr["Predictie"] as AdomdDataReader)
                           {

                               while (pred.Read())
                               {

4. Nu exista o modalitate standard de a obtine un DataTable dintr-un AdomdDataReader   - iar GetSchemaTable nu intoarce rezultatele ca schema. Asa ca am ajuns la modalitatea obisnuita de a genera DataTable :

while (dr.Read())
                       {
                           using (AdomdDataReader pred = dr["Predictie"] as AdomdDataReader)
                           {

                               int fields = pred.FieldCount;
                               DataTable dt = new DataTable("nume");
                               for (int i = 0; i < fields; i++)
                               {
                                   dt.Columns.Add(pred.GetName(i), pred.GetFieldType(i));
                               }
                               while (pred.Read())
                               {
                                   object[] p = new object[fields + 1];
                                   for (int i = 0; i < fields; i++)
                                   {
                                       p[i] = pred[i];
                                   }
                                   dt.Rows.Add(p);
                               }                                
                           }

De ce n-am facut-o extension method la AdomdDataReader    ? Din YAGNI ( Ok, puturosenie …) Daca o sa fie nevoie , (re)fac…

5. E clar ca nu merge rapid cu BI-ul …nici macar cu ceva simplu ca un forecast amarit …Deci,la treaba!

.NET | BI | sql
Sunday, July 05, 2009 9:44:00 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Monday, June 22, 2009


Cum sa faci un javascript in ASP.NET 2.0 care sa poata sa afiseze ceva pe un alt site

Ok, titlul e cam naspa . Sa incerc sa o iau altfel : Orice site de informatii are un script js prin care alte site-uri preiau informatia(bineinteles, este o chestie de reclama)

Si iar revin la marota mea,www.infovalutar.ro, care avea preluare de curs prin PHP,Java, .NET, Python – dar nu avea prin Jscript (ceea ce majoritatea competitorilor aveau ) . Asa ca am fost fortat sa ma gindesc ;-)

OK, imi trebuie un js care sa fie interpretat O chestie simpla era sa fac un js care sa se interpreteze pe server – dar nu aveam chef:

  1. Sa ma rog de fiecare data de hosting
  2. Sa trec js-urile printr-un proces suplimentar( chiar daca stiu ca asp.net verifica existenta tag-urilor si, daca nu sunt, lasa neprelucrat…)

E clar ca problema ar trebui inversata – si anume, avut “ceva” care se interpreteaza pe server care sa intoarca rezultatul . Clara solutia acum : un generic handler, de tipul ashx, care intoarce document.write(“text”);

Doua sfaturi:

  1. Aveti grija sa escapati “ in text , daca ati pus document.write(“text”).Daca nu puneti asa ceva, va afiseaza o pagina goala.
  2. Incercati sa il faceti cit mai generic posibil  - s-ar putea sa aveti nevoie de el si la alte proiecte.

Referitor la 2, eu am obtinut 2 clase:

clsTable – care preia niste stari de tipul cellpadding,backgroundcolor, tdbgcolor etc – astfel incit fiecare sa poa sa isi preia informatia avind culorile/fontul personalizat

clsConnect :ConfigurationSection : care intoarce datele din BD . E deriata din ConfigurationSection  astfel incit sa o pun in web.config(app.config) si sa uit de ea.

Demo gasiti la http://infovalutar.ro/webmaster.aspx . Daca cineva poate crede ca este util, voi posta si sursele

.NET | ASP.NET | curs valutar | jscript | programare
Monday, June 22, 2009 5:08:58 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  |  Trackback


Tuesday, April 21, 2009


Chart Image si Real internet site

Cum am spus, am trecut www.infovalutar.ro de la asp.net 1.1 la ASP.NET MVC.Trecerea nu a fost usoara, si inca sunt citeva lucruri de facut.

Totusi una din probleme care mi-a dat de furca a fost ca ChartImage , la refresh, nu se mai afisa. Foloseam asta la afisarea grafica a datelor cursurilor, de ex. http://infovalutar.ro/bnr/graphic/usd 

Bun … problema era ca stergea fisierul png generat. Am pus “deleteAfterServicing “  la false  * si o sa le sterg in momentul in care generez cursurile.

Totusi, mai aveam o problema . Daca accesam site-ul cu Firefox si dadeam refresh, se vedea. Dar aceeasi pagina , cu IE 7 , nu mai afisa  - desi in codul HTML generat codul de la AXD era ACELASI, IMAGINEA era pe hard …

Dupa mai multe cautari am dat de pagina asta, http://blogs.msdn.com/deliant/archive/2008/12/02/managing-chart-generated-images-with-chart-image-handler.aspx care are TOATE setarile si ma dat de privateImages … L-am pus la false si gata!

Rezumat : pentru a folosi ChartImage cu succes cu IIS 7 aveti nevoie de 3 setari:

<appSettings>
   <add key="ChartImageHandler" value="storage=file;privateImages=false;timeout=600;dir=….;deleteAfterServicing=false;" />
  </appSettings>

 

A doua in httphandlers

<httpHandlers><add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />

A treia in handlers

<add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 

 

Si, bineinteles, daca hostingul nu a instalat inca controalele, sa puneti din references System.Drawing si System.Web.DataVisualization “Copy local” la true – ca sa le aveti in bin

Succes!

.NET | Asp.NET MVC | chart | curs valutar | programare
Tuesday, April 21, 2009 4:47:11 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Sunday, March 01, 2009


Salvarea versiunilor fisierelor aplicatiei

O sa vorbesc acum despre salvarea versiunilor fisierelor aplicatiei. De ce avem nevoie de asa ceva? Din cel putin doua motive:

  1. Daca suntem programatori intr-o echipa , atunci fiecare are nevoie sa aiba acces la toate fisierele aplicatiei si sa le puna intr-un loc central(repository), de unde sa poata sa le ia si ceilalti pe PC-ul propriu ( check-out) , sa le modifice si sa le puna inapoi (check-in). Daca nu le pune inapoi si ramine la versiunea anterioara, atunci operatiunea se cheama „undo check-out”.
  2. Daca vrem sa vedem ce modificari au fost facute intre 2 versiuni ale fisierelor – asemanari, deosebiri ...

Exista mai multe solutii pentru asta.Doua dintre ele sunt Microsoft Source Safe si Visual Studio Team System . Noi o sa folosim ceva gratuit, si anume subversion. O sa mergem pe calea usoara, si anume svn1clicksetup , http://svn1clicksetup.tigris.org/ . Eu am instalat vers 1.3.3 . Nu va ingrijorati de detalii ... apasati doar next si retineti folder-ele unde se instaleaza, inclusiv username si parola pe care v-o cere.

Acum sa creeam repository – acesta il putem face in c:\svnrepos\book35. Creeam aceasta cale, click dreapta pe c:\svnrepos\book35 si alegem TortoiseSVN =>Create repository here. Acum trebuie sa aducem fisierele aplicatiei: Dam click dreapta pe c:\book35, TortoiseSVN =>import, si la url punem file:///C:/svnrepos/book35 . Ok, acum, daca ne ducem pe TortoiseSVN =>RepoBrowser , si dam file:///C:/svnrepos/book35 , o sa vedem toate fisierele aplicatiei.

Bun, deci repository este file:///C:/svnrepos/book35 . Ar trebui sa luam fisierele de acolo – folosim TortoiseSVN =>SVN Checkout in ce folder dorim. Sa zicem , pentru a da un exemplu, ca modificam app.config si mai adaugam un spatiu in el. Dupa ce salvam , dam click si o sa apara „SVN Commit”. Apasam pe el si la mesaj dam „test”. Daca mergem acum pe file:///C:/svnrepos/book35 , TortoiseSVN=> RepoBrowser, si mergem pe app.config, click dreapta, show log vedem ca are 2 versiuni. Mai mult, le putem compara vizual!

Cam asta a fost despre salvarea versiunilor fisierelor

Tema pentru acasa :

Instalati ce versiune de Source Control vreti, modificati un fisier de 3 ori si salvati pe hard versiunea nr 2. Cum ati face daca ati avea mai multe fisiere si ati vrea pentru toate versiunea nr 2?

Lecturi recomandate:

Un tutorial mai lung de SVN aici, http://www.shokhirev.com/nikolai/programs/SVN/svn.html

Continuous integration - de ex., http://martinfowler.com/articles/continuousIntegration.html

Introduction to Team Build and Continuous Integration.

.NET | programare | tutorial .NET3.5
Sunday, March 01, 2009 11:05:34 PM (GMT Standard Time, UTC+00:00)  #    Comments [3]  |  Trackback


Wednesday, February 25, 2009


2 rezolvari si 1 sfat

Aseara am inceput sa trec infovalutar pe Asp.NET MVC.Si aveam 2 probleme :

1. degeaba ii dadeam Home/Index/3 ca in controller-ul

    public class HomeController : Controller

    {

        public ActionResult Index(string Banca)

        {

            ViewData.Model = new CurrencyList();

            ViewData["Bank"] = Banca;

            return View("Index");

        }

Nu vroia sa imi ia id-ul(parametrul Banca era null) si gata, indiferent cum ii dadeam eu Home/Index/BNR sau Home sau orice altceva –desi trecea prin procedura.

M-am gindit sa dau vina pe Asp.NET MVC, dar , fiind un framework folosit de atitia, nu ma  gindeam ca tocmai eu am un caz deosebit …Si citisem ca pe IIS integrated NU trebuie sa ii faci modificari …

2. Cind incerca sa se conecteze la Sql Server, imi dadea “login failed for user …”

Am incercat sa refac login-ul , sa schimb parola, ce nu am incercat …

Asa ca m-am dus la culcare si am revenit cu sentimente mai bune de dimineata.

Rezolvari :

1.  M-am dus sa ma uit cum e inregistrat routing-ul in global.asax.Cum sa fie , obisnuit:

routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "BNR" }  // Parameter defaults
            );

Si mi-a cazut fisa : parametrul de la functia index nu se cheama cum vrea el, ci cum vrea MVC – adica id

public ActionResult Index(string id) fata de public ActionResult Index(string Banca)
        Naspa! Mi-aduce aminte de Java, cind numele clasei = numele fisierului !

2. Am incercat , in disperare , sa ma conectez si de pe Sql Server Management Console – acelasi mesaj : “Login Failed” . In disperare, ma conectez cu credentialele de Windows si ma uit in log-urile de la SQL Server – Management/Sql Server Logs  - si acolo mi-a zis ca nu se poate ca nu este configurat in mixed mode …

Ce sa mai zic  ? Schimb, dau restart la Sql, merge!

Sfat catre mine : Daca nu iti iese , du-te si te culca sau apuca-te de altceva. Revii cu mintea odihnita dupa aceea!

.NET | ASP.NET | Asp.NET MVC | programare
Wednesday, February 25, 2009 5:47:38 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, February 15, 2009


NDepend

E buna si criza asta la ceva … precum si blog-ul meu pentru mine. Am primit de la Patrick Smacchia o licenta de NDepend . Si ce ar fi mai bun decit sa analizez aplicatia deja facuta?

Nu pot sa spun decit ca raportul lui, gata facut , este super impresionant (se pot defini rapoarte custom, dar ideea este ca astepti sa iasa ceva din prima)

Iata, de exemplu, imaginea cu dependentele:

image

Se vede dintr-o data ce nu e bine: SuffixDLL are legatura la PropertyGridUtils – cind ar trebui sa aiba doar SuffixWnd ( daca nu e clar, sa explic : Dll-ul de business nu ar trebui sa aiba de a face cu interfata grafica …)

Mai mult decit FxCop , are si multe detalii referitoare la calitatea codului in sine, de ex:

WARNING: The following CQL constraint is not satisfied. 1 types on 21 tested match the condition. --> Group {Unused Code / Dead Code}

// <Name>Potentially unused types</Name>
WARN IF Count > 0 IN SELECT TOP 10 TYPES WHERE
TypeCa == 0 AND     // Ca=0 -> No Afferent Coupling -> The type is not used in the context of this application.
!IsPublic AND       // Public types might be used by client applications of your assemblies.
!NameIs "Program"   // Generally, types named Program contain a Main() entry-point method and this condition avoid to consider such type as unused code.

types
Afferent coupling at type level (TypeCa)
Full Name

Settings
0
SuffixWnd.Properties.Settings

 

Intr-adevar, pusesem settings la un moment dat  - si apoi nu il folosisem.

Un tool de avut pentru orice team leader de .NET!

Site http://www.ndepend.com/, recomandare de la Scott Hanselman si un podcast , precum si demo-uri

.NET | ndepend | programare | usual tools
Sunday, February 15, 2009 9:51:21 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Friday, February 13, 2009


Sumar Creeare Aplicatie

Rezumat aplicatie:

1 ora si 46 de minute  : Creeare 

2 ore si 10 minute : cautat implementare pe asp.net, facut password invizibil

1ora si 22 minute: about box, serializare date

4 ore si 3 minute : localizare property grid

36 minute :fisier minimal de help

40 minute : localizare ASP.NET

Total : 10 ore si 37 de minute .

Concluzii :

1. Creearea efectiva este doar 20% din munca. Restul ( adica fine tuning) ramine la 80% – respecta deci principiul lui Pareto .

2. Daca esti microISV , ai nevoie de o mare rabdare in a termina o aplicatie.

3. Release early se pare ca intr-adevar functioneaza – am primit feedback imediat.

 

Pe de alta parte cu ce nu sunt multumit este ca nu am separat interfetele de la propertygrid utils , de a trebuit in site-ul web sa fac referinta la ceva care continea windows forms. Dar pentru o prima aproximare...merge...

Gasiti aplicatia de downloadat aici http://serviciipeweb.ro/downloads/pwdgen/ si un site minimal aici http://serviciipeweb.ro/downloads/pwdgen/index.aspx

 

Se ofera cineva continue in Silverlight si/sau WPF ?

 

Pentru referinta:

Partea 1, Geneza si creearea unei aplicatii minimale

Partea 2, Adaugare site

Partea 3, serializarea setarilor pentru Windows Forms

Partea 4, Localizare aplicatie

Partea 5, Terminat aplicatia – help si localizare ASP.NET

Partea 6, Sumar Creeare Aplicatie

.NET | Creeare Aplicatie | programare
Friday, February 13, 2009 3:45:40 AM (GMT Standard Time, UTC+00:00)  #    Comments [1]  |  Trackback


Thursday, February 12, 2009


Terminat aplicatia – help si localizare ASP.NET

Revenit la 16 : ok , help-ul. Pentru Help vom folosi fisiere HTM si HTML Help Compiler-ul (http://www.microsoft.com/downloads/details.aspx?familyid=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en)

Scris rapid in engleza ... si acum sa il punem in aplicatie cu HelpProvider. 16:15 Pus KeyPreview la true pe forma – merge!

Ura -avem o aplicatie completa pentru ClickOnce! Sa ii facem deploy! Ii punem minor pe 1 – si vom astepta 7 zile sa isi faca update-ul

I-a pus tot versiunea 1.0 in fisierul HTML . Sa stergem default.htm si sa mai incercam 1 data. Ups – ma uitam in alta parte...pusese bine – dar deschidea pagina de pe site, nu pagina de pe loca.

OK, mi-a inclus traducerea – dar nu fisierul de help – sa il specificam sa il puna la deploy– Nu merge! La naiba, probabil fiindca e Express nu poate include alte fisiere. Sa mai citim ...Oh – se pare ca daca ii pun Build Action la Content merge... Super! 16:29

Sa le publicam pe ftp si sa facem proba . Merge - sa dezinstalam si sa mai ne racorim un pic : 16:36

Ramine modificarea aspx ca fie localizat. S-ar parea ca se termina ?

8:15 No hai si cu localizarea pe aspx... as vrea sa o fac din pagina aspx, nu sa mai scriu cod... Sa vedem daca pot ...

8:41 nu ... asa ca o sa il scriem in pagina – OK, 8:52 Deploy site, verify : 8:55 Total 40 de minute

Uff , gata ! nu mai am rabdare sa fac si Silverlight, si WPF – si poate o comunicatie prin WCF

 

Partea 1, Geneza si creearea unei aplicatii minimale

Partea 2, Adaugare site

Partea 3, serializarea setarilor pentru Windows Forms

Partea 4, Localizare aplicatie

Partea 5, Terminat aplicatia – help si localizare ASP.NET

Partea 6, Sumar Creeare Aplicatie

.NET | Creeare Aplicatie | programare
Thursday, February 12, 2009 3:24:00 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Wednesday, February 11, 2009


Localizare aplicatie

Acum, Back to work : 7:27 . Ar trebui sa fac mai intii Localizarea si apoi fisierul de Help –din simplul fapt ca si fisierul de Help ar trebui localizat. OK, sa ii dam drumul inainte sa dam drumul la twitter sau alte prostii de Web 2.0 ...

Ce ar trebui sa fac la localizare este sa fac un fisier de resurse pe care sa il foloseasca si exe-le de Windows , si asp.net-ul .

Facut un dll de resurse, adaugat fisier de resurse, pus NameSite ,scris clasa care sa intoarca din resource , pus Nunit test:

objCI = new CultureInfo("fr-FR");

Thread.CurrentThread.CurrentUICulture = objCI;

OK – merge : 7:47 . Sa facem munca de rutina si sa traducem tot(google translate )... Sa ii dam drumul !- si sa modificam internal class ResStrings in public class ResStrings

Rulat din nou clasa de testare – ups ... greseala – metodele pe resurse sunt statice (7:59)... Revenim la hardcodare... si terminam la 8:04 . Acum ne trebuie customizat PropertyGrid – daca am fost puturosi si nu am pus textbox / label ...

Ar trebui sa incep sa mut toate chestiile legate de property grid in assembly-ul lor ... Si mi-ar place ca grid-ul sa reactioneze la tab.
Sa derivam deci gridul si PropertyAttributes

La naiba! 9:32 - o ora si jumate! Dar a durat sa integrez resursele mele cu atributele – si a trebuit sa folosesc reflection pentru creere...

Dar , cel putin, merge GlobalizedDescriptionAttribute –si am facut si testul ...

Acum numele categoriilor...Si incepe sa fie stupid : CategoryAttribute : are GetLocalizedString , pe cind DescriptionAttribute NU! Alooo ... chiar 2 echipe de programatori ?? Ma rog! Bine ca macar unul are ceva sa ma ajute!

OK – modificat categoria si descrierea – acum ar trebui chiar NUMELE proprietatii...Sa ne cufundam in codul PropertyInfoDescriptor ... OK ... reusit( era vorba de override DisplayName) !-10:42 si acum sa trecem sa modificam peste tot.

Dar inainte , un pic de pauza – desi sunt acasa in zi libera, totusi mai am ceva de testat pentru servici.

11:15 - am inceput din nou ...si am terminat la 11:15 sa traduc.

Acum ar trebui sa fac kit de setup ... si sa fac help – si sa traduc site-ul asp.net. Dar plec pe afara : 11:30 inca citeva ore...

Partea 1, Geneza si creearea unei aplicatii minimale

Partea 2, Adaugare site

Partea 3, serializarea setarilor pentru Windows Forms

Partea 4, Localizare aplicatie

Partea 5, Terminat aplicatia – help si localizare ASP.NET

Partea 6, Sumar Creeare Aplicatie

.NET | Creeare Aplicatie | programare
Wednesday, February 11, 2009 8:22:19 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, February 10, 2009


Creearea unei aplicatii minimale : serializarea setarilor pentru Windows Forms

Revenit la sentimente mai bune la 11:00 PM si incercat sa termin cit mai mult din proiect.

Revenind : Parola/Salt/ Afisat sau [pus ca password text in Windows Application dupa o setare ( nu cu un enum , desi ar fi mai frumos - dar am codul http://www.codeproject.com/KB/architecture/dynamicattributes.aspx)

– salvarea acestei setari, teste pe Windows Forms : 11:19.

Acum un about box s-ar cam impune… buton, forma, testat : 11:24

Lansare de pe usb – asta inseamna sa salvez eu setarile intr-un fisier de configurare aflat fie linga aplicatie, fie undeva in alta parte…

Asa ca trebuie renuntat la application settings – si serializat clasa in XML. Scris codul de salvare(XML Serializer sa traiasca ) – intrebarea este : unde scriu unde se salveaza fisierul ??? Asa ca o sa incerc in 2 moduri : mai intii sa vad daca nu am un fisier pe care sa il citesc linga aplicatie – si apoi sa citesc din folderul de date al aplicatiei.

public string FileName

{

get

{

if (File.Exists(AppDataXML))

{

FileInfo fi = new FileInfo(AppDataXML);

if (HasAccess(fi.FullName))

return AppDataXML;

}

string Data =Path.Combine( System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),AppDataXML);

return Data;

}

}

private bool HasAccess(string File)

{

try

{

FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.Append | FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, File);

f.Demand();

return true;

}

catch (SecurityException ex)

{

string s = ex.Message;

return false;

}

}

Pus XMLIgnore la ceea ce nu vreau sa serializeze ( uff : mai bine faceau invers –sunt mai multe chestiile pe care vreau sa le ignor : sa nu fi facut bine clasa ? Dar nu – e vorba de afisare in grid si implementare ICustomTypeDescriptor )

Terminat si asta : ora 12:17. Inceput sa scriu un test,terminat si executat : 12:22.Asta denota ca am scris bine clasa.

Revenind : ce mai am ?

Fisierul de Help

Localizare

Of... iar am obosit :Total munca : 1 ora si 22 de minute. La culcare iarasi!

Partea 1, Geneza si creearea unei aplicatii minimale

Partea 2, Adaugare site

Partea 3, serializarea setarilor pentru Windows Forms

Partea 4, Localizare aplicatie

Partea 5, Terminat aplicatia – help si localizare ASP.NET

Partea 6, Sumar Creeare Aplicatie

.NET | Creeare Aplicatie | programare
Tuesday, February 10, 2009 10:35:00 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, February 09, 2009


Continuare creere aplicatie minimala

Revenind 2:41 AM :

Inca trei cerinte:

5. Cineva si-a manifestat dorinta ca sa nu se vada salt-ul in clar, ci sub forma de *** . Ar fi usor de pus [PasswordPropertyText(true)] dar as vrea sa fie dinamic

6. Sa poti alege locatia fisierului de salvare a salt-ului si a parolei - bun pentru a lua aplicatia pe usb

7. Site web.

Pentru 5, dupa ce m-am batut cu IcustomTypeDescriptor, am vazut codul de aici:

http://www.codeproject.com/KB/architecture/dynamicattributes.aspx

No, si dupa ce am copiat si m-am batut cu el, a mers cu bool, nu a mai mers cu un enum

[Flags]

public enum FormatAsPassword

{

None = 0,

Password=1,

Salt=2,

Site=4

}

Asa ca il las balta si pun doar la password …raminind pe alta data, dupa ce mai studiez nebunia… 3:48

Sa incep cu altceva mai rewarding –sa mi se para ca am facut ceva: site-ul web:

Ar fi frumos daca ar fi un property grid pentru ASP.NET ( si free , daca se poate)…Gasesc unul care pare bun, http://www.codeproject.com/KB/custom-controls/xacc_propertygrid.aspx, dar care spune ca e broken pentru IE7.

La naiba, sa vedem!3:58

Cind zicea ca arata nasol in IE7 nu se incurca… la fel de nasol arata si in Firefox

clip_image002

OK, deci nu… de la capat. Table, textbox, label

4:41 – terminat. Acum sa pun site-ul sus.

4:52- merge- acum, la culcare! – dupa 2 ore si 10 minute – nefacut mare lucru. Daca nu ma complicam cu cele 2( property grid pe asp.net si customtypedescriptor) , acum erau gata mai multe

 

Partea 1, Geneza si creearea unei aplicatii minimale

Partea 2, Adaugare site

Partea 3, serializarea setarilor pentru Windows Forms

Partea 4, Localizare aplicatie

Partea 5, Terminat aplicatia – help si localizare ASP.NET

Partea 6, Sumar Creeare Aplicatie

.NET | Creeare Aplicatie | programare
Monday, February 09, 2009 10:27:00 PM (GMT Standard Time, UTC+00:00)  #    Comments [2]  |  Trackback




Geneza si creearea unei aplicatii minimale

Asa cum am scris si pe blog-ul propriu, sunt multe site-urile la care m-am inscris – si majoritatea cu aceeasi parola(de fapt, cam 3 parole diferite). Intre ele, si ejobs-care tocmai a fost spart.Asa ca am decis sa fac o mica aplicatie care, in functie de numele site-ului, sa genereze un sufix la o parola deja existenta.Aplicatia va trebui sa fie in doua flavors : Windows Forms si Web Form (ASP.NET) .

Cit va dura ?Probabil 2 – hai 4 ore… vom vedea! Care este estimarea voastra ?

Aceasta este relatarea cum am facut proiectul -inceput la 3:32 AM.

clip_image002

Citit pe net rapid de criptografie, terminat clasa : 3:57 AM.Adaugat proiect de test cu NUnit.Pentru

public void TestEncryption()

{

clsAddSufix c = new clsAddSufix();

c.Password = "parolagenerica";

c.NameSite = "www.ejobs.ro";

c.Salt = "onenewkey";

Console.Write(c.Generate());

}

am concluzionat ca e prea greu de tinut minte o parola de tipul:

parolagenerica+WdUDoNZBW3+jlUTTj+Q2b6qil0=

asa incit am decis sa o simplific – ce ar fi daca as aduna byte rezultat ?

Super! Imi da parolagenerica2377 ! Dar ar trebui sa verific ca 2 site-uri imi dau 2 parole diferite

Jale mare- Nunit imi da cu rosu – ma uit in cod –si vad ca am pus NameSite nu il folosesc- asa ca modific codul…

Super! Totul cu verde!

Acum ar trebui sa fac GUI … 4:32 – dupa ce am incercat sa pun label+textbox in table layout, i-am dat seama ca property grid ar face treaba mai usoara… <Intrerupere pina la 5:46>

Pus sa afiseze “on the fly” parola rezultat – 6:09

Verificat - si vazut ca nu se modifica daca modific site-ul – pentru ca gridul nu isi face refresh. Modificat sa implementez INotifyPropertyChanged.Modificat frumusetea

public string NameSite { get; set; }

in

public string NameSite

{

get

{

return _NameSite;

}

set

{

_NameSite = value;

RaisePropertyChanged("NameSite");

if (Autogenerate)

{

RaisePropertyChanged("Result");

}

}

}

Testat- nu se intimpla nimic…OK, am inteles – interceptat evenimentul PropertyChanged si facut refresh pe grid :

Modificat si celelalte proprietati, 6:34

Adaugat test – verde!

Acum ar trebui avertizat utilizatorul despre ce mai trebuie adaugat - adaugat IDataErrorInfo : 7:00

Ar trebui sa salvez setarile (salt,parola) in setarile aplicatiei.

7:04.

Modificat target framework din 3.5 in 2.0- 7:10 si 109 warnings…

Facut kit de setup pentru clickonce

Deploy si verificat :7:20

Total 1 ora + 46 minute

Totusi, au mai ramas citeva lucruri:

1. Help

2. About

3. Localizare

4. Salvare pe codeplex

Despre astea, data viitoare… Inca o data – care este estimarea voastra?

Partea 1, Geneza si creearea unei aplicatii minimale

Partea 2, Adaugare site

Partea 3, serializarea setarilor pentru Windows Forms

Partea 4, Localizare aplicatie

Partea 5, Terminat aplicatia – help si localizare ASP.NET

Partea 6, Sumar Creeare Aplicatie

.NET | Creeare Aplicatie | programare
Monday, February 09, 2009 5:24:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Wednesday, January 28, 2009


Expresii regulate si Regulazy

Am avut de facut urmatoarea chestie : de citit fisiere dintr-un folder si updatat text-ul din ele ( erau niste csv-uri) cu portiuni din denumire( de exemplu, daca fisierul se numeste vinzari_123 sa pun in fisier 123 la fiecare rind) . Normal ca m-am gindit sa il fac cit mai “extensibil” – pentru ca nu stiu forma sub care vin fisierele – asa ca m-am gindit sa evaluez ceea ce obtin cu expresii regulate – si sa le pun intr-un fisier de configurare( despre ConfigurationSection intr-un post viitor). Dar nu mai tineam minte sintaxa – in schimb tineam minte ca Roy Osherove a facut un Regulazy ( vedeti pagina http://weblogs.asp.net/rosherove/pages/tools-and-frameworks-by-roy-osherove.aspx ).

Cum se utilizeaza : Pui textul in casuta si apesi Regex_edit

102153_ReguLazy by Roy Osherove Beta_active

Incepi sa subliniezi portiuni din text si dai click dreapta ( eu am facut asta cu vinzari –si am selectat “1 or more anything”. Apoi am selectat _ , am dat click dreapta si am selectat “exactly _”  . In sfirsit am selectat 123 ,am dat click dreapta si am selectat “digits”.Iar click dreapta pe 123 selectat si dau “rename”  - si ii pun numele “values”. Daca apas acum pe “test again input” se vede clar ca obtin in “values” ce am nevoie – si anume 123.

102804_ReguLazy by Roy Osherove Beta_active

Ce mai am de facut este sa apas pe “generate”  si a iesit codul :

public void SampleRegexUsage()
{
    string regex=@"^\w+?_(?<values>\d+)$";
    RegexOptions options = RegexOptions.Multiline;
    string input= @"vinzari_123";
    MatchCollection matches = Regex.Matches(input,regex,options);
    foreach (Match match in matches)
    {
        Console.WriteLine(match.Value);
        Console.WriteLine("values:" + match.Groups["values"].Value);
    }
}

( ma rog, trebuie sa scot multiline si sa scot ^ de la inceput … – dar fara asta e corect!)

Eu zic ca e un tool super rapid si usor de folosit( si free ;-)  – si bun pentru cazul cind nu folosesti de multe ori expresii regulate.

.NET | programare | regex | usual tools
Wednesday, January 28, 2009 11:30:24 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, January 26, 2009


DasBlog si feedburner sau de ce e important in open source sa nu hard codezi API

Am vrut sa vad si eu citi cititori am pe blog-uri ( si sa le pun si reclame -  dar asta e deja o alta discutie … ) .

Asa incit am cautat “feedburner dasblog” – si am gasit o configurare usoara aici :dasBlogAndFeedburner.aspx" href="http://mikeknowles.com/blog/2008/12/30/dasBlogAndFeedburner.aspx">http://mikeknowles.com/blog/2008/12/30/dasBlogAndFeedburner.aspx

OK  - am pus in site.config , am profitat de faptul ca acest blog este deja pe feedburner , am rescris web.config (am pus un spatiu ca para ca este nou) – si merge de minune – se duce la http://feeds2.feedburner.com/AndreiIgnatBlog

Eh – acum intervine problema : pentru blog-ul propriu am facut acelasi lucru – cu mentiunea ca l-am adaugat in feedburner. Problema a venit in momentul verificarii : se ducea la http://feeds.feedburner.com/blogpropriu in loc de http://feeds2.feedburner.com/blogpropriu  . Am inceput sa ma uit in cod – si vad intr-adevar:

if (siteConfig.FeedBurnerName != null && siteConfig.FeedBurnerName.Length >0)
            {
                return new Uri(new Uri("http://feeds.feedburner.com/"),siteConfig.FeedBurnerName).ToString();
            }

 

Naspa … Problema este ca feeds.feedburner.com NU mai merge pentru noile RSS-uri, ci doar pentru cele vechi. Daca era o intrare de ex, <FeedBurnerApi>http://feeds.feedburner.com/{0}</FeedBurnerApi> mergea de minune acum configurarea.Dar asa va trebui sa recompilez / sau sa contribui la dasBlog/Release/ProjectReleases.aspx?ReleaseId=17989" href="http://www.codeplex.com/dasBlog/Release/ProjectReleases.aspx?ReleaseId=17989">http://www.codeplex.com/dasBlog/Release/ProjectReleases.aspx?ReleaseId=17989 – mai ales ca Google transfera feedburner si are un alt URL.

Am cautat pe feedburner   - dar nu am gasit sa faca redirectarea .Ma rog, o sa le scriu celor de la feedburner sa vad daca imi permit sa am si URL-ul cu feeds in loc de feed2.

Concluzie : Daca lucrati la on software OpenSource si vreti ca oamenii sa il foloseasca, nu hard-codati nici un API al unui third party – tot ce folosit adaugati in fisierul de configurare…

.NET | dasblog | programare
Monday, January 26, 2009 8:57:10 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Monday, January 19, 2009


Creearea Bazei de date – si suport filestream in Sql Server 2008

Deocamdata o sa facem doar tabelele pentru detaliile/resursele care tin de un Angajat . Hai sa enumeram citeva :

  1. Un Angajat are nume( se poate schimba – prin casatorie, de ex.), prenume , poza – sa le numim proprietati UserRelated
  2. Un Angajat poate avea telefon , laptop – sa le numim proprietati JobRelated
  3. Un Angajat poate avea cont de Active Directory, email , Citrix , acces VPN - sa le numim ITRelated

(Daca aveti si alte sugestii,va rog sa imi scrieti)

Evident ca am putea creea o tabela prin care sa avem , ca si coloane, toate aceste proprietati - dar aplicatia nu ar fi destul de flexibila, in cazul in care cineva ar vrea sa mai adauge un detaliu/resursa ar trebui sa refacem aplicatia. Asa incit totul se rezolva cu un nivel de indirectare – o sa creez o tabela care sa contina gruparile de Proprietati (UserRelated, JobRelated , ITRelated) –, una care sa contina Proprietatile( nume, prenume, poza, telefon, laptop, email, etc) si una care sa faca legatura intre ele. De asemenea , trebuie ca tabelele sa contina date despre cine a introdus informatia si pina cind e valabila – acestea vor fi 3 cimpuri, continute tot timpul in (aproape) fiecare tabela , de tipul :

[DateModified<NumeTabela>] [datetime] NULL, --data modificarii

[NameUserModified<NumeTabela>] [nvarchar](150) NULL, - nume utilizator care a modificat

[IPModified<NumeTabela>] [nvarchar](150) NULL, -- ip-ul de la care s-a produs modificarea

Deocamdata am ajuns la urmatoarea structura :

clip_image002

Pentru conformitate , iata scriptul de creere al tabelelor si scriptul de creere a resurselor/detaliilor Angajatului.

http://serviciipeweb.ro/iafblog/content/binary/net35/bd/1/db.zip

Ce vreau sa fac in continuare este sa fac coloana ValueBinaryUserGroupProperty de tipul FileStream – adica sa isi pastreze datele pe hard, de fapt.

Verificam ca serverul suporta filestream – click dreapta pe server, “properties”, selectati “Advanced” si verificati ca filestream este OK:

clip_image004

Apoi click dreapta pe baza de date, “properties”, selectati FileGroups si acolo adaugati un filestream(bifati si “default”)

clip_image006

Acum trebuie sa adaugam un file ca sa putem profita de acest filestream . Trebuie ales File_Type : “filestream data”, filegroup-ul si, cel mai important, folder-ul in care sa il punem (ca alegere usoara, este acelasi folder ca fisierul primar de date)

clip_image008

Acum putem sa construim tabela noastra cu filestream – stergem tabela accUserGroupProperty (drop table accUserGroupProperty ) si o creeam cu suport de FileStream :

CREATE TABLE [dbo].[accUserGroupProperty](

[IDUserGroupProperty] [uniqueidentifier] NOT NULL ROWGUIDCOL PRIMARY KEY,

ToDateUserGroupProperty datetime NULL,

[ValueTextUserGroupProperty] [nvarchar](max) NULL,

[ValueBinaryUserGroupProperty] [varbinary](max) FileStream NULL,

[IDUser] [bigint] NOT NULL,

[IDProperty] [bigint] NOT NULL,

[DateModifiedUserGroupProperty] [datetime] NULL,

[NameUserModifiedUserGroupProperty] [nvarchar](150) NULL,

[IPModifiedUserGroupProperty] [nvarchar](150) NULL,

)

Ce ne trebuie neaparat pentru o coloana de tipul FileStream :

  1. Suport Server, BD ( facut deja)
  2. O coloana in tabela respectiva de tipul NOT NULL ROWGUIDCOL PRIMARY KEY

Cu ce ne afecteaza : cu aproape nimic – dar e bine sa poti vedea fisierele pe hard * de ex., poza angajatului o sa fie direct pe hard in loc sa o stocam in BD.

Nu uitati ca tot ce am facut aici prin click-uri se poate face si prin script, cu ajutorul butonului “Script” – se poate gasi usor in toate pozele precedente

Tema pentru acasa : Creeati o baza de date cu support filestream, o tabela cu o coloana filestream si inserati un text. Observati modificarile de pe folder-ul unde ati spus sa se creeze FileStream.

Lecturi Recomandate:

FileStream cu SQL Server (pe scurt)

http://blogs.microsoft.co.il/blogs/bursteg/archive/2008/05/09/sql-server-2008-filestream-part-1.aspx

Database normalization

http://en.wikipedia.org/wiki/Database_normalization

Developing Time Oriented databases in SQL

http://www.cs.arizona.edu/people/rts/tdbbook.pdf

.NET | programare | tutorial .NET3.5 | tutoriale
Monday, January 19, 2009 10:06:02 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, January 06, 2009


Asp.NET Chart Controls

Pentru ca la nu imi mergea Reporting Services( un IIS pe o masina cu 64 de biti, cu Sql pe 32 si cu Web Extensions de aspnet exe pe 32 de biti disabled, ca altfel nu merge alt site) a trebuit sa fac un raport cu numere. Si, pentru ca un grafic spune cit 100 de cuvinte, am zis sa le fac si citeva grafice. Si am fost bucuros sa dau o sansa la noile controale de chart. In 15 minute am reusit sa fac ceva ok –sunt super

Citeva caveats, totusi :

  1. Downloadati NEAPARAT toate documentele, adica
  2. Download the free Microsoft Chart Controls

    Download the VS 2008 Tool Support for the Chart Controls

    Download the Microsoft Chart Controls Samples

    Download the Microsoft Chart Controls Documentation

    SI mai ales Download the Microsoft Chart Controls Samples – si rasfoiti exemplele.

  3. Vedeti ca in web.config baga o inregistrare de tipul
  4. <add key="ChartImageHandler" value="storage=file;timeout=20;dir=x:\inetpub\etc\log;" />

    Acolo x:\inetpub\etc\log trebuie sa fie calea catre un director in care IIS sa aiba dreptul de scriere….

  5. Daca nu aveti acces la masina de hosting ca sa instalati in GAC chart-urile, puteti copia de la voi de pe masina
  6. System.Web.DataVisualization.dll
    System.Web.DataVisualization.Design.dll

    ( folositi subst X %windir%\assembly – si copiati-le din X)

     

Daca vreti poze frumoase , gasiti la Scott . Oricum, sunt foarte bune – si mai bune decit vechiul Chart Control din VB6…Folositi cu incredere!

.NET | ASP.NET | chart | programare
Tuesday, January 06, 2009 10:11:46 PM (GMT Standard Time, UTC+00:00)  #    Comments [5]  |  Trackback


Sunday, January 04, 2009


New Year Resolution

Pentru activitatea mea profesionala, mi-as dori:

  1. Sa termin aplicatia de management al angajatilor dintr-o firma
  2. Sa reusesc sa invat Azure
  3. Sa reusesc sa invat Workflow Foundation

Voi ce v-ati dori?

(pentru mine personal am scris aici)

PS: stiti carti bune despre Workflow Foundation ?

.NET | azure | programare
Sunday, January 04, 2009 11:20:40 PM (GMT Standard Time, UTC+00:00)  #    Comments [1]  |  Trackback


Wednesday, December 03, 2008


Descrierea aplicatiei

Aplicatia pe care m-am gindit sa o facem va realiza urmatoarele:

    Va tine o evidenta (paralela !) a angajatilor dintr-o firma ( va fi integrat Active Directory si va tine datele intr-o baza de date Sql Server 2008)

    Va tine o evidenta a conturilor acestora pe diverse aplicatii, precum si a diferitelor beneficii ale user-ilor ( telefon, laptop, etc)

    Va face un workflow pentru un nou angajat, astfel incit sa se stie sigur cine ce are de facut( cumparat birou, laptop, etc)

    Pentru toate aceste actiuni se va tine o evidenta a celor care adauga/modifica date in sistem.

    Pe masura ce vom dezvolta aplicatia, ii vom adauga tot felul de noi functionalitati.Sa o numim Evidan(de la Evidenta Angajati)

 

Sa definim principalele roluri de actiune asupra sistemului:

  1. Administrator – are "puterea" de a "sterge" un angajat daca acesta nu a avut atribute, precum si de a defini atributele Workflow-ului si ale angajatului / aplicatiilor.
  2. Responsabil : indeplineste un anumit punct al workflow-ului pentru un nou angajat( ii da telefon, laptop, birou, il introduce in Active Directory, creeaza un email )
  3. HelpDesk – introduce / sterge atributele user-ului
  4. Raportare –are dreptul sa extraga un raport de pe site

 

Cerintele de lucru pentru versiunea 1 :

  1. Definirea workflow-ului si administrarea acestuia
  2. Importul angajatilor din Active Directory
  3. Trecerea unui angajat nou prin workflow
  4. Trecerea unui angajat care pleaca prin workflow
  5. Vizualizarea etapelor workflow-ului pentru angajat
  6. Vizualizarea resurselor care tin de un angajat.

Sunt deschis la sugestii pentru orice imbunatatire

.NET | programare | tutorial .NET3.5
Wednesday, December 03, 2008 5:23:56 AM (GMT Standard Time, UTC+00:00)  #    Comments [7]  |  Trackback


Friday, November 21, 2008


Ajutor la Tutorial .NET 3.5

La fiecare parte a tutorialului( sau aproape ) o sa am citeva chestii pe care trebuie sa le faca cititorul singur.

De exemplu, la cel cu "aplicatii mici de test" am dat ca tema de casa realizarea aceleiasi aplicatii in Powershell. Daca cineva m-ar ajuta sa realizez temele de casa (cu poze despre cum l-a facut) , pot oferi ca recompensa :

  1. Un link pe blog catre blog-ul lui
  2. O revista Sql Server Magazine ( e adevarat, citita....) –daca e prin Bucuresti si ne putem intilni ...Prin posta cred ca e mai mare daraua decit ocaua...
  3. Cistigarea proprie de experienta despre cit de greu/usor se scrie un tutorial...
  4. Habar nu am ce si-ar mai putea dori, dar puteti face sugestii rationale.

Ce ziceti ?

.NET | programare | tutorial .NET3.5
Friday, November 21, 2008 4:37:56 AM (GMT Standard Time, UTC+00:00)  #    Comments [4]  |  Trackback


Tuesday, November 18, 2008


APLICATII MICI DE TEST

Acum vom trece aplicatia minimala de consola in mai multe outputuri : Windows Forms, Asp.NET, WPF

Vom transforma aceasta aplicatie intr-una de Windows Forms

Click dreapta pe solutie, Add=> New Project, Windows Forms Application

 

Dublu click pe form1, luam un buton din Toolbox , dublu click pe el, si apare evenimentul de click

 

 

Copiem exemplu de la aplicatia ConsoleApplication1, modificand Console.Write in MessageBox

In figura alaturata se vede ca nu aplicatia nu stie cine este SqlConnection. Dar, imediat in stinga, exista un icon mic -daca dati click pe el, o sa vedeti ca stie - alegeti "using"

 

 

Alegeti "set as startup project"

 

 

CTRL+F5 si apasati pe "buton1" - ar trebui sa va apara

 

 

 

Ce am observat ? Ca am scris de 2 ori acelasi cod. Daca am avea de modificat, nu ar fi cam greu in aceasta aplicatie -dar pentru o aplicatie mare am putea intimpina probleme. Ar fi bine daca acest cod s-ar tine undeva , intr-o locatie comuna - ceea ce in Windows numim dll.

OK - sa adaugam un dll - click dreapta pe Solution, Add=>New Project , Class Library

A aparut "Class1" si adaugam codul de pe Consola, modificat putin - nu mai interceptam SqlException -ca nu am stii ce sa intoarcem ( de fapt, ar trebui sa ne facem clasa noastra de exceptii - dar despre asta mai tirziu) - si intoarcem chiar ce gasim in BD:

    public string MessageFromBD()

{

using (SqlConnection sc = new SqlConnection())

{

sc.ConnectionString = @"Server=.\SqlExpress;Database=testAndrei;Trusted_Connection=True;";

sc.Open();

using (SqlCommand sco = new SqlCommand())

{

sco.CommandType = CommandType.Text;

sco.CommandText = "select top 1 Test from TestTable";

sco.Connection = sc;

string text = sco.ExecuteScalar().ToString();

return text;

}

}

 

}

 

 

Bun - acum sa chemam acest mesaj si in consola, si in Windows Forms.La amindoua dam click dreapta pe "References", "Add reference", "projects"

Selectam ClassLibrary1 si dam OK. Puem pe Console Application1 set as startup

Inlocuim codul din ConsoleApplication1, Program cu urmatorul:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data;

using System.Data.SqlClient;

namespace ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

try

{

ClassLibrary1.Class1 p = new ClassLibrary1.Class1();

string text = p.MessageFromBD();

Console.WriteLine("found " + text);

}

catch (SqlException ex)

{

Console.WriteLine(" Eroare conexiune:" + ex.Message);

return;

}

 

 

}

}

}

 

CTRL+F5,ca sa vedem rezultatul. Daca merge, haidem sa il modificam si pe cel de Windows Forms( nu uitati sa puneti referinta si set as startup)

 

Bun - acum vom face si o aplicatie WPF -click dreapta pe solutie, Add=>New Application, WpfApplication.

Adaugati referinta la ClassLibrary1, adaugati acelasi cod ca la Windows Forms si CTRL+F5

 

Ultimul pas, facem o aplicatie Web pentru aceasta aplicatie:

In carte=>testBD creeam un folder numit WebApplication1.Apasam "Start=>Run , control panel( swtich to classic view daca scrie asa ceva), administrative tools, Internet Information Services"

Expandati "local computer ", "WebSites","Default Web Site", click dreapta pe "default web site",new , "Virtual directory"

 

La alias scrieti "WebApplication1" si la Directory scrieti calea catre folder ( la mine, C:\carte\testBD\WebApplication1)

Asigurati-va ca la click dreapta pe "WebApplication1" , properties, ASP.NET, versiunea este 2.0

 

 

Bun - acum sa creeam aplicatia. Pornim Microsoft Visual Web Developer 2008 Express Edition si "File=>OpenWebSite, Local IIS" si expandati pina dati de WebApplication1

 

 

 


Acum adaugam dll-ul care facea comunicarea cu BD:

 

File=> Add=> Existing project si navigati pina la ClassLibrary1( la mine, C:\carte\testBD\ClassLibrary1). Adaugati csproj.Adaugam referinta la dll: La fel, click dreapta pe http://localhost/WebApplication1 , add reference, projects, classlibrary1

Acum adaugam pagina unde o sa vedem mesajul :

click dreapta pe http://localhost/WebApplication1 , add new item, Web Form ( fiti atent in ce limbak dati -C# sau VB.NET...)

Acum, gasiti jos Design - apasati pe el

 

 

 

Din toolbox alegeti din nou butonul , trageti pe forma si dati dublu click

Vom pune (aproape) acelasi cod ca si pentru WindowsForms/Console/WPF:

protected void Button1_Click(object sender, EventArgs e)

{

try

{

ClassLibrary1.Class1 p = new ClassLibrary1.Class1();

string text = p.MessageFromBD();

Response.Write("found " + text);

}

catch (SqlException ex)

{

Response.Write(" Eroare conexiune:" + ex.Message);

return;

}

}

 

Apasati CTRL+F5, apasati pe buton si ar trebui sa va scrie:

"Eroare conexiune:Cannot open database "testAndrei" requested by the login. The login failed. Login failed for user 'TEST1\ASPNET'. "

Mai tineti minte ca am folosit conexiunea trusted :

sc.ConnectionString = @"Server=.\SqlExpress;Database=testAndrei;Trusted_Connection=True;";

 

Acum, haideti sa ne identificam cum trebuie si in ASP.NET. click dreapta pe http://localhost/WebApplication1 , add new item,Web Configuration File(lasati numele de Web.Config asa cum este!), gasiti authentication si puneti linga:

<identity impersonate="true"/>

CTRL+F5 din nou si acum apare:

Eroare conexiune:Cannot open database "testAndrei" requested by the login. The login failed. Login failed for user 'TEST1\IUSR_TEST1'.

Tare, nu ? Am schimbat un user cu altul - din ASPNET, sub care ruleaza ASP.NET, am schimbat IUSR_TEST1 - sub care rulam default.

Hai sa facem ultima schimbare , ca sa ne recunoasca IIS :

Apasam "Start=>Run , control panel( switch to classic view daca scrie asa ceva), administrative tools, Internet Information Services"

Click dreapta pe "WebApplication1" , properties, Directory security, Anonymous access, Edit,scoateti "Anonymous Access"

 

OK si iar OK. Ne intoarcem la aplicatie si...Ura!, merge:

 

 

 

 

Observatii:

  1. Daca, in loc sa utilizam conexiunea "trusted"( Trusted_Connection=True ) foloseam una in care sa avem credentiale de SQLServer( de ex., sa cu ce parola ati dat) nu ne mai loveam de impersonare..

     

  2. Acest lucru ne-a facut atenti si la aplicatia Windows Forms – e clar ca ea se bazeaza tare pe faptul ca suntem utilizatori "preferentiali" – cu drepturi de administrator – pentru SQL Server

     

  3. Puteti downloada proiectele de la adresa http://serviciipeweb.ro/iafblog/content/binary/net35/small/small.zip si http://serviciipeweb.ro/iafblog/content/binary/net35//small/smallBD.zip

     

  4. Tema pentru acasa : realizati aceeasi aplicatie in Silverlight (Hint :In Asp.NET, pe proiect,dati click dreapta, add new File=>Silverlight application)

 

 

Lecturi Recomandate:

    How to implement impersonation in an ASP.NET application, http://support.microsoft.com/default.aspx/kb/306158

.NET | programare | tutorial .NET3.5
Tuesday, November 18, 2008 3:43:51 AM (GMT Standard Time, UTC+00:00)  #    Comments [2]  |  Trackback


Tuesday, October 28, 2008


Cod sursa pentru librariile .NET

 

La un moment dat aparuse stirea ca putem face debug chiar in codul sursa al librariilor .NET , vezi aici

http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx

Problema era de download rind pe rind...

Dupa aceea , ca sa ne fie mai usor, cineva s-a gindit sa downloadeze totul intr-o singura bucata – si asa a aparut NetMassDownloader

http://www.codeplex.com/NetMassDownloader

Si , in cele din urma, a venit normalul – aveti librariile de downloadat aici

http://referencesource.microsoft.com/netframework.aspx

Numai sa va tina banda...altfel, sunt interesant de citit * si , daca va uitati, exista si un BigInt implementat ...

Pe deasupra, puteti vedea ce greseli faceti ( sau ce e prost implementat in framework ;-) ) daca va da vreo eroare ciudata ...

 

PS : Pentru cei care asteapta tutorialul de .NET 3.5 : e f. greu de scris in fiecare saptamina, asa incit o sa aiba o aparitie bilunara (marti , de obicei)

.NET | programare
Tuesday, October 28, 2008 2:46:18 PM (GMT Standard Time, UTC+00:00)  #    Comments [2]  |  Trackback


Sunday, October 19, 2008


Tutorial .NET 3.5 – prima parte

Ce vrem sa facem

Prin acest tutorial vrem sa facem o introducere in programarea cu frameworkul .NET 3.5 . Vom realiza o aplicatie de tinerea evidentelor activelor angajatilor unei intreprinderi. Intentia este sa o trecem , realizind diverse feature(raportare, integrare Active Directory,etc) cam prin tot ceea ce inseamna programarea in .NET : de la WebSite la WindowsForms, trecind prin WebService, etc.

Acesta nu va fi un tutorial de programare- nu vom incepe cu ceea ce inseamna variabile, i++ si alte lucruri de genul acesta. Pentru aceasta va rog consultati, de ex., http://www.microsoft.com/romania/educatie/cursnet/default.mspx (aveti varianta pentru elevi si pentru profesori)

Vom realiza acest lucru cu editiile Visual Studio Express ( http://www.microsoft.com/express) raminind ca, pe masura ce se poate, sa aratam diferentele intre ele si celelalte.

Sa trecem la treaba!

 

 

Primul pas : instalarea software-ului free

 

Acest pas se efectuează o singura date pe PC. Este vorba despre instalarea server-ului de Web , precum si a Visual Studio Express ca si unealta de dezvoltare. Este cel mai lung pas, dar, precum am spus, se efectuează o singura data.

 

Să începem: ai Windows (XP, de preferinţă) si ne asiguram ca ai server-ul de Web (Internet Information Services – IIS de acum înainte) pe maşină .Pentru aceasta te duci in "Control panel" => "Administrative Tools" si verificaţi ca există.

 

    Daca nu exista, mergeţi înapoi la "Control Panel", apăsaţi pe "Add or Remove programs" si apăsaţi pe "Add/Remove Windows Components". Bifaţi IIS ca in imagine si daţi "Next"( asiguraţi-vă ca aveţi CD-ul de instalare Windows prin apropiere)

 

 

Bun – acum o sa instalam VS 2008 Express. Acesta este free si îl puteţi descărca de la adresa

http://www.microsoft.com/express/download/ . Acolo , jos de tot, gasiţi o imagine ISO (VS2008ExpressWithSP1ENUX1504728.iso) pe care o puteti downloada . O puteţi vedea cu ISObuster, Daemon Tools or Virtual CloneDrive ( căutaţi-le pe google pentru linkuri de download) sau cu un program făcut de MS, Virtual CD-ROM Control Panel for Windows XP care poate fi downloadat de la adresa:

http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe

Pentru o adresa mai scurta, incercati http://tinyurl.com/winxpvirtualcdcontrolpanel

Pentru instalare incarcati CD-ul si , daca aveti autorun, va va aparea imaginea urmatoare:

 

Vom instala C# si WebDeveloper. Cei care vor o varianta in VB.NET , exista un traducator intre sintaxe la adresa http://www.carlosag.net/Tools/CodeTranslator/ si altul la http://www.developerfusion.com/tools/convert/csharp-to-vb/

Cind instalati , deselectati SQL Server – il vom instala mai tirziu

 

Daca ati terminat de instalat si C# si WebDeveloper, urmatorul pas este sa instalati Powershell de la adresa http://www.microsoft.com/powershell. Spre deosebire de VS sau SQL Server, acesta cere Microsoft Genuine validation .

Ne instalam si Windows Installer 4.5 de la http://www.microsoft.com/downloadS/details.aspx?familyid=5A58B56F-60B6-4412-95B9-54D056D6F9F4&displaylang=en ( sau http://tinyurl.com/wininst4-5 ) . Atentie sa luati pe specificul sistemului dumneavoastra( de ex., pentru Windows XP pe 32, luati WindowsXP-KB942288-v3-x86.exe)

 

Acum putem instala SQL Server Express Edition with Advanced Services SP2 de la adresa http://www.microsoft.com/express/sql/download/default.aspx . Luati SQL Server 2008 Express with Advanced Services - o sa facem si rapoarte in Sql Reporting si multe altele.Va duceti pe "planning" si alegeti "system configuration checker". Daca ati trecut toate, atunci putem da pe "installation"-"new sql server stand alone ….". OK-dupa o suita de"Next" ajungeti la "Feature Delection" – dati "Select all".

La "database engine" dati o parola pentru sa si nu uitati sa apasati "add current user"

 

De asemenea nu uitati de "Filestream", care rezolva problema veche:"sa pastrez documentele in BD sau doar un link catre calea lor?"

Acum ramine doar "Next"…si sa restartati PC-ul - de siguranta si ca sa porneasca serviciile automat, nu sa le porniti din control panel=>services.msc

In cele din urma mai avem nevoie, pentru Silverlight , de downloadat Microsoft® Silverlight™ Tools for Visual Studio 2008 SP1 (RC1) de la adresa http://www.microsoft.com/downloads/details.aspx?FamilyID=c22d6a7b-546f-4407-8ef6-d60c8ee221ed&DisplayLang=en

Acum, despre inregistrare : daca va inregistrati download-urile , atunci primiti citeva chestii free –intre care mie mi-au placut imaginile . Vedeti http://www.microsoft.com/express/registration/

Lecturi recomandate:

    Dan Fernandez , Top 15 Things to love about Visual Studio 2008 Express - http://blogs.msdn.com/danielfe/archive/2007/11/19/top-15-things-to-love-about-visual-studio-2008-express.aspx

    Curs .NET Framework - http://www.microsoft.com/romania/educatie/cursnet/default.mspx

    Petzold , .NET Book Zero - http://www.charlespetzold.com/dotnet/

 

 

 

 

.NET | programare
Sunday, October 19, 2008 12:52:06 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  |  Trackback


Wednesday, September 03, 2008


SiteMap, query string si editare ulterioara

 

Am avut de facut , de multe ori, site-uri care cuprindeau pagini de genul : Lista, Editare, Editare proprietati ( de ex., Lista User ( cu cautare + sortare), Editare User, Editare Proprietati UserCurent).Problema intervine cind vrei sa ii lasi si un site map – si ai urmatoarea structura : Lista User-i => Editare User => Editare proprietati user si , dupa ce user-ul este pe pagina de editare proprietati, revine la Editare User - de unde stii ce user ai editat ? De obicei pasezi id-ul in query string ...dar cum il pui in sitemap ?

Solutia rapida pe care o gasisem(nu foarte corecta, dar rapida ) a fost sa tin in Session ultimul user care este editat.Nu prea mi-a placut – mult de scris, de repetat.

Ma uitasem si la pagina aceasta, de modificat nodurile in memorie, dar iar nu mi-a placut.

Simteam ca trebuie sa fie ceva in XMLProvider ... dar nu reuseam sa ii dau de cap.

Dupa mult timp, am dat de pagina asta

http://www.csharper.net/blog/custom_sitemapprovider_incorporates_querystring_reliance.aspx

care mi-a rezolvat problema, prin mostenire de la XMLSiteMapProvider.

Ce trebuie sa faceti :

 

  1. Copiati codul de la adresa http://www.csharper.net/blog/custom_sitemapprovider_incorporates_querystring_reliance.aspx

    Sau de aici

public class SmartSiteMapProvider : XmlSiteMapProvider

{

    public override void Initialize(string name, NameValueCollection attributes)

    {

        base.Initialize(name, attributes);

        this.SiteMapResolve += new SiteMapResolveEventHandler(SmartSiteMapProvider_SiteMapResolve);

    }

 

    SiteMapNode SmartSiteMapProvider_SiteMapResolve(object sender, SiteMapResolveEventArgs e)

    {

        if(SiteMap.CurrentNode == null)

            return null;

 

        SiteMapNode temp;

        temp = SiteMap.CurrentNode.Clone(true);

        Uri u = new Uri(e.Context.Request.Url.ToString());

 

        SiteMapNode tempNode = temp;

        while(tempNode != null)

        {

            string qs = GetReliance(tempNode, e.Context);

            if(qs != null)

                if(tempNode != null)

                    tempNode.Url += qs;

 

            tempNode = tempNode.ParentNode;

        }

 

        return temp;

    }

 

    private string GetReliance(SiteMapNode node, HttpContext context)

    {

        //Check to see if the node supports reliance

        if(node["reliantOn"] == null)

            return null;

 

        NameValueCollection values = new NameValueCollection();

        string[] vars = node["reliantOn"].Split(",".ToCharArray());

 

        foreach(string s in vars)

        {

            string var = s.Trim();

            //Make sure the var exists in the querystring

            if(context.Request.QueryString[var] == null)

                continue;

 

            values.Add(var, context.Request.QueryString[var]);

        }

 

        if(values.Count == 0)

            return null;

 

        return NameValueCollectionToString(values);

    }

 

    private string NameValueCollectionToString(NameValueCollection col)

    {

        string[] parts = new string[col.Count];

        string[] keys = col.AllKeys;

 

        for(int i = 0; i < keys.Length; i++)

            parts[i] = keys[i] + "=" + col[keys[i]];

 

        string url = "?" + String.Join("&", parts);

        return url;

    }

}

(inca o data: nu e codul meu, ci al lui C# Shiznit,http://www.csharper.net/blog/custom_sitemapprovider_incorporates_querystring_reliance.aspx)

 

  1. Puneti in web.config urmatoarele:

    <siteMap defaultProvider="SmartSiteMapProvider" enabled="true">
    <providers>
    <clear />
    <add name="SmartSiteMapProvider" type="SmartSiteMapProvider" siteMapFile="web.sitemap" securityTrimmingEnabled="true" />
    </providers>
    </siteMap>

     

  2. In web.sitemap folositi reliantOn

    <siteMapNode url="~/EditUser.aspx" title="Editare utilizator" reliantOn="UserID" />

     

  3. GATA!

 

Ce mai poate fi facut ? Poate sa ia nu doar din QueryString, ci si din Form.

 

.NET | ASP.NET | programare
Wednesday, September 03, 2008 2:30:02 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Tuesday, August 26, 2008


Change Data Tracking(kind of) in C#

Sa zicem ca suntem in C#,avem SQL 2005 si o tabela( de ex., utilizatori) pe care trebuie sa implementam un (fel de ) mecanism de CDC – automat.

 

Creeam o noua tabela, utilizatori_history,identica cu precedenta, la care adaugam 3 cimpuri ( de_la_data, la_data, si stare : insert, update, delete)

Ne jucam cu Linq 2 SQL (pentru ca e foarte rapid) – si am vrea ca sa se faca (relativ) automat – adica sa nu lasam la latitudinea celor care folosesc clasa utilizatori daca sa inregistreze sau nu istoricul.

Nici o problema – in DataContext, pentru fiecare tabela, exista un eveniment de <insert-update-delete> de tipul partial void <Metoda><NumeTabela>(<tabela> nume), in cazul nostru partial void InsertUtilizatori(Utilizatori instance)

Super – e suficient sa interceptam evenimentul si sa scriem datele intr-o noua instanta de utilizatori_history , o adaugam la this.Utilizatori_history si facem submitchanges impreuna cu this.ExecuteDynamicInsert(instance); pentru a salva utilizatorii noi.

Din pacate, ne trage in piept ... si anume o eroare ca nu avem voie sa facem acest lucru in metoda...Si are (partial) dreptate.

Asa incit solutia alternativa (nu foarte buna, dar merge) este sa creeam un nou data context de la 0:

        MyDataContext my=new MyDataContext(this.Connection);     //pastram aceeasi conexiune

my.Transaction =this.Transaction;                  //si tranzactie

my. Utilizatori_history.InsertOnSubmit(history);

my.SubmitChanges();

 

Cam asta ar fi ... Ma rog, daca vrem si informatii aditionale( de ex., ce user a fost, etc) le putem adauga in history la creearea obiectului istoric.

Ce ar mai fi de facut, daca nu ar fi fost facut in SQL2008:

    Adaugat prin Code generat , pentru fiecare tabela din DataContext, una de history – si suprascris fiecare eveniment...

 

 

.NET | LINQ | programare
Tuesday, August 26, 2008 1:24:46 PM (GMT Daylight Time, UTC+01:00)  #    Comments [1]  |  Trackback


Monday, August 18, 2008


Linq Data Source , Object Data Source si GridView

 

In sfirsit am avut ocazia sa ma joc cu LINQ de adevaratelea(cam tirziu, avind in vedere ca a aparut Visual Studio 2008 SP1 si The .NET Framework 3.5 SP1 cu DataEntity si Astoria). Si prima chestie mare pe care a trebuit sa o fac a fost un gridview cu paginare, sortare si filtrare.

Imi generasem clasele Linq intr-un dll – si am zis ca pun un LinqDataSource. Cind citesc documentatia , gasesc TableName – si mi-am zis: "UPS... nu vreau sa ma conectez la tabela, ci la datele mele"

Asa incit imi zic – ObjectDataSource e ceea ce vreau.

Il configurez – punindu-i metodele pe care le vroia – cea cu selectcount si cea cu paginare - si mergea OK. In SQL Server Profiler aparea Ok... Si acum filtrarea pe server . Aici au inceput problemele: Nu mai voia sa afiseze paginile (1, 2 ,etc), desi selectcount-ul il facea pe server...

Ca solutie intermediara am zis sa aduca toate datele daca face filtrare... Dar nu mi-a placut prea mult...si in plus nu mai genera evenimente de rowcommand...

Asa ca intreb si eu ca incepatorul pe Ronua si am noroc :sirocco imi raspunde ca TableName e de fapt numele clasei ... Chiar asa este!Merge paginarea si sortarea rapid si fara probleme...

Iar la filtrare e suficient sa puneti un parametru la WhereParameters si sa puneti clauza Where cum trebuie .

Ma rog, am mai dat de o problema : Am filtrat dupa stringuri - merge NumeProprietate.Contains(@numeparametru).

Problema este ca ,daca nume parametru este gol, va da eroarea

No applicable method 'Contains' exists in type 'String'

Nu va speriati – eroare spune o prostie ... puneti la parametru ConvertEmptyStringToNull="false"

 

 

.NET | ASP.NET | LINQ | programare
Monday, August 18, 2008 10:52:06 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Tuesday, August 12, 2008


Master page si erori

Incercasem sa interceptez erorile din Master page – si nu intelegeam de ce nu merge. Pina mi-am adus aminte ca Master deriva din control – si ca, de fapt, este un control instantiat de pagina, nu invers…

Totusi, o functionalitate buna a Master este cea de afisare de erori la nivel central ( ca si cum ai avea un control de afisare erori).
In App_Code se adauga un fisier .cs de forma

   

public class ErrorAdd : IValidator

{

   

    public ErrorAdd(string Message)

    {

        ErrorMessage = Message;

    }

   

   

    public string ErrorMessage { get; set; }

   

   

    public bool IsValid

    {

        get

        {

            return false;

        }

        set

        {

   

        }

    }

   

    public void Validate()

    {

   

    }

   

}

 

 (clar invalid...)

Apoi in Master adaugam un control ValidationSummary si urmatorul cod :

 public void AddTheError(string Message)

    {

        ErrorAdd e = new ErrorAdd(Message);

        this.Page.Validators.Add(e);

   

    }

   

Cam de atit e nevoie … La orice cod de pe pagina – de pilda, pe evenimente, scrieti

  try

        {//cod

  }

        catch (Exception ex)

        {

            this.Master. AddTheError(ex.Message);

        }

 Singura problema pe care o vad este sa folosesti acelasi master pentru mai multe functionalitati ...Nu vrei un God Object, nu-i asa?

.NET | ASP.NET | programare
Tuesday, August 12, 2008 10:52:54 PM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  |  Trackback


Wednesday, August 06, 2008


Linq si testare

 

Ma tot joc cu LINQ 2 SQL de citva timp– si sunt impresionat de cit de repede te poti misca in el (chit ca viitorii programatori nu trebuie sa invete sql cu el … e suficient sa scrii sintaxa in VB.NET /C# de Where si ti-o converteste el … impresionant)

Oricum pentru testarea obiectelor ma gindisem la Linq 2 Objects – ca sa nu tot dau in Baza de date( sindromul NIH) . Din pacate, nu am reusit sa  fac ceva  - asa ca a doua solutie, google, a fost cu success.

De la adresa http://andrewtokeley.net/Images/andrewtokeley_net/Downloads/LinqToSQL.zip

gasiti un proiect de testare, bazat tot pe Linq2Objects  - mai exact, pe List<>.

   

Ca sa il folositi faceti asa:

            Adaugati fisierele din folder-ul Interfaces , precum si cele din Mocks ( fara ExampleMockDatabase.cs)

            Adaugati DataContextWrapper.cs

   

Adaugati, dupa exemplul ExampleMockDatabase.cs , BD a  dvoastra( sa zicem MockAndreiMemoryDatabase ) si scrieti codul pentru CreateTables si PopulateTables

Trimiteti catre programul principal prin Inversion of control un IQueryable pentru tabela TabelaMea  proprietatea TabelaMea  din urmatorul cod:

   

   public class AndreiFind

    {

        MockDataContextWrapper d = new MockDataContextWrapper(new MockAndreiMemoryDatabase());

        public IQueryable<Tabela> TabelaMea

        {

            get

            {

                return d.Table< TabelaMea>().AsQueryable<TabelaMea >();

            }

        }

         

    }

Descrierea autorului aici http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx

.NET | LINQ | programare | testare
Wednesday, August 06, 2008 3:51:18 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Wednesday, July 30, 2008


Despre fundatiile programarii

Am aflat de pe blogul lui Gabriel Enea, http://gabrielenea.blogspot.com/2008/07/bazele-programarii-sau-cum-sa-scrii.html , despre o carte numita Foundations of Programming - Building Better Software, by Karl Seguin .

Exceptionala si va sfatuiesc si pe voi sa o cititi. E usor de citit si scrisa cu nerv.

Alegerile pe care le face nu sunt intotdeauna pe gustul meu(ca Nhibernate, de ex.) dar in rest este o carte care iti reia/reda bunurile obiceiuri in dezvoltarea soft.

Ce mi-a placut :

    Pagina 13 :

"The idea behind domain driven design is to build your system in a manner that's reflective of the actual

problem domain you are trying to solve. This is where domain experts come into play – they'll help you

understand how the system currently works (even if it's a manual paper process) and how it ought to

work. At first you'll be overwhelmed by their knowledge – they'll talk about things you've never heard

about and be surprised by your dumbfounded look. They'll use so many acronyms and special words

that'll you'll begin to question whether or not you're up to the task. Ultimately, this is the true purpose

of an enterprise developer – to understand the problem domain. You already know how to program, but

do you know how to program the specific inventory system you're being asked to do? Someone has to

learn someone else's world, and if domain experts learn to program, we're all out of jobs."

 

    Pagina 30: despre IOC sau DI intr-un mod clar , cu Structure Map

    Pagina 36 : uitasem de assembly: InternalsVisibleTo

    Pagina 61 : de ce ati trece o instanta a unei clase cu ref ...

Chiar daca sunteti f. buni , citi Foundations of Programming - Building Better Software, by Karl Seguin .

. Merita!

 

 

    

.NET | carti | programare
Wednesday, July 30, 2008 1:58:16 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Tuesday, July 22, 2008


Documentatie proiecte NET

Stiam ca a a aparut Sandcastle final. Dar, desi are GUI-ul incorporat si command line-ul, e inca destul de greu de folosit. Asa ca am cautat pe codeplex ceva care sa se integreze usor, in afara de SHFB

Asa am gasit DocProject . Acesta iti adauga un nou tip de proiect in VS, ii spui printr-un Wizard ce proiecte vrei sa iti adauge, iti spune ce lipseste pentru a compila in CHM sau HxS + 1 Site ...E clar ca e super OK si iarasi e clar ca trebuie sa il compilezi doar "on demand" la sfirsitul proiectului – adica sa nu il lasi sa se compileze la fiecare build decit daca ai masina super tare – RAM si RPM.

In alta ordine de idei, fisierele CHM le poti vedea usor, dar cele HxS nu... Am descoperit un Hxs viewer bun si free aici : http://www.helpware.net/mshelp2/h2viewer.htm

 

.NET | programare | Sandcastle
Tuesday, July 22, 2008 4:34:50 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Thursday, June 19, 2008


Data Table sau Ienumerable to Excel/Word / PDF
Am reusit sa fac ceea ce vroiam de mult ... Sa export din DataTable sau IEnumerable<T> direct in Excel / Word / PDF ...
Codul este pe CodePlex Am vrut sa il pun si pe code project, dar datorita faptului ca sunt foarte succint, mi l-au sters (aproape) imediat. Asa ca il scriu aici

Introduction

The project exports a DataTable or IEnumerable to Word / Excel / PDF / CSV / HTML / CSV

Background

Make extensive use of

  1. String Template - for rendering templates(EXcel 2003, Word 2003 , HTML,CSV)
  2. OfficeSDK for rendering the Word /Excel 2007
  3. itextsharp. for exporting to PDF from XML.

Using the Code

Every programmer have a DataTable or IEnumerable and wants to export to the user in an easy way.

This project enables an easy and customizable way to export data to various formats.

            
DataTable dta = new DataTable("andrei");
dta.Columns.Add(new DataColumn("ID", typeof(int)));
dta.Columns.Add(new DataColumn("Data", typeof(string)));
dta.Rows.Add(1, "test 1 & <");
dta.Rows.Add(2, "test 2 ");
dta.Rows.Add(3, "test 3 >");

dta.ExportTo(ExportToFormat.Excel2007, @"C:\andrei.xlsx");

dta.ExportTo(ExportToFormat.Word2003XML, @"C:\andrei.doc");


dta.ExportTo(ExportToFormat.Word2007, @"C:\andrei.docx");


dta.ExportTo(ExportToFormat.itextSharpXML, @"C:\aitext.xml");

dta.ExportTo(ExportToFormat.Excel2003XML, @"C:\andrei.xls");


dta.ExportTo(ExportToFormat.HTML, @"C:\andrei.html");


dta.ExportTo(ExportToFormat.XML, @"C:\andrei.xml");

dta.ExportTo(ExportToFormat.PDFtextSharpXML, @"C:\andrei.pdf");


Points of Interest

The String Template is really really great. I think that a good programmer can make a second CodeSmith from there...
The itextsharp has some problems with XML transformation to PDF. Please check whitespaces after xml tags if it says something like " can not transform table into paragraph"
The OfficeSDK is really great - and really easy to use.

History

Version 1

.NET | programare
Thursday, June 19, 2008 10:43:36 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Wednesday, June 11, 2008


change data capture si Pwershell
SQL 2008 (inca in CTP ...) aduce o veche idee sub o forma noua - Change data capture( CDC )

Practic monitorizeaza DML+ DDL (insert, update delete, add/remove column)pe o tablea prin citirea din log, folosindu-se de un job pentru asta.
Cam toata lumea care se ocupa cu Baze de date (BD)a facut asa ceva... o tabela de log pentru alta tabela+ trigger-i pe insert/update/delete.

Citeva observatii:
    1. nu logheaza cine a facut - deci neaparat tabela va trebui sa contina un identificator al persoanei, sa ai pe cine da vina
    2. nu are interfata grafica - si am facut un proiectel, CDCHelper
( e adevarat, motivat si de Contest Sql Heroes )

Acuma ma interesa sa ii fac si un command line - nu de alta, dar pare mai usor in command line.
Asa ca am zis -de ce nu PowerShell ?Tot se incearca impunerea lui, de vine in Server 2008 instalat by default
Asa ca, dupa ce am incercat sa citesc documentatia si m-am cam incurcat, am dat de urmatoarele link-uri - si dezvoltarea cu VS2008 a fost super usoara :


PowerShell - A file hasher cmdlet and the Extended Type System explained - B# .NET Blog

Windows PowerShell Visual Studio 2005 Templates (C# and VB.NET)

David Aiken : Creating a Windows PowerShell CmdLet using the Visual Studio Windows PowerShell

Ce avantaje am la PowerShell vs command line in dezvoltare  ? Unul singur : poti defini rapid parametrii- si , daca sunt obligatorii, are grija el...
Acum, ce mi-ar trebui, este sa am aceasi idee de parametrii si in commandline - adica sa ii definesc ca in Powershell si "cineva", alt dll, sa ii reinterpreteze...
Dar cred ca asta e alt proiect

Proiectul pentru CDC il gasiti aici
http://www.codeplex.com/CDCHelper

.NET | programare | sql | PowerShell
Wednesday, June 11, 2008 3:54:47 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Saturday, June 07, 2008


calendar pentru asp.net
Din pacate controalele MS nu au inclus si un calendar un ASP.NET.... asa ca trebuie sa ne descurcam cum putem.
Metoda cea mai simpla este sa il fortezi pe user sa scrie intr-o forma data, de ex. yyyy-MM-dd HH-mm-ss ( HH este pentru ora in range-ul 0-24 ...hh pentru 0-12 - cite neplaceri am avut din aceasta cauza...)

Cealalta metoda este sa gasesti un calendar deja facut - sau evaluat. Asa ca m-am bucurat cind Scott Mitchell a facut evaluarea unui calendar free, RJS Calendar
Din ceea ce a scris in evaluare parea OK, asa incit l-am pus la incercare cu Master Pages.
Citeva probleme intimpinate:
    1. Nu isi face propriul director de CSS -trebuie copiat
    2. Adaugat din toolbox mai incearca sa scrie citeva chestii si in web.config -si il busheste - salvati o copie a web.config, comparati si modificati

Dupa ce reusesc eu sa compilez in sfirsit site-ul, la afisarea paginii - eroare! Nu gasea controlul textbox asociat...Normal - master pages ca de obicei prefixeaza id-urile de la controale.

Asa ca Reflector-ul + plug-inurile de decompilare mi-au fost prieteni apropiati... si am reusit sa identific linia la

Me._ValidateControl.PopCalID = Me.ID

care trebuia rescrisa

Me._ValidateControl.PopCalID = Me.UniqueID

Acum - singura problema pe care o am este daca respect Microsoft Public License (Ms-PL) .... In rest este un calendar pe care il recomand si eu cu caldura...

.NET | ASP.NET | programare
Saturday, June 07, 2008 1:32:24 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1]  |  Trackback


Wednesday, May 21, 2008


ginduri razlete - si probleme la fel
Superb articolul despre Arhitectura de la A la Z
Merita citit si(mai ales) de catre programatori


Probleme cu o aplicatie la servici : pusesem Web Deployment project, facusem site-ul ne updatabil - si , la un moment dat, urla ca site-ul nu este precompilat
"The file has not been pre-compiled, and cannot be requested. "
Ce ii lipsea ? Facusem o referinta cater un dll global ...
Cum am descoperit ? Am facut siteul sa fie updatabil, si atunci a spus ce ii lipseste...

Imi dadea la un moment dat eroare la linia
DateTime.ParseExact("2007-11-11 15:14:12","yyyy-MM-dd hh:mm:ss")
Nu intelegeam de ce ...pina la un moment dat mi-am dat seama ...
Trebuia
DateTime.ParseExact("2007-11-11 15:14:12","yyyy-MM-dd HH:mm:ss")
24 ore = HH

Am avut probleme la Web.Config cu autorizarea
Puneam
     <authorization>       
      
<deny users="*"/>
        <allow roles="xxx"/>      
      </authorization>


Eram in rolul xxx... si totusi nu imi dadea acces.
Ideea este ca ordinea NU este comutativa, trebuie scrise mai intii autorizarile
     <authorization>       
      
<allow roles="xxx"/>      
       <deny users="*"/>       
      </authorization>


Imi place din ce mai mult XP -  si incep sa ma rog pentru verde...Iar VS e o adevarat bomboana pentru asta ...Cind genereaza method stub( scriind , de ex., instanta.Metoda ... si geenrind codul pentru metoda inexistenta ... apasati pe coltul de la cuvintul Metoda ) scrie codul punind in corp

throw new NotImplementedException();

Este super ... apare rosu ... si pe urma apare faimosul verde ...




.NET | ASP.NET | programare
Wednesday, May 21, 2008 6:35:39 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Thursday, May 08, 2008


de ce nu sunt Scott Hanselman
Unul din motive - pentru ca nu am darul lui de a prezenta informatia tehnica.
Vroiam sa scriu un post in care sa explic ca, pentru site-uri Web, a fi de .NEt 3.5 inseamna a avea un AppPool de .NET 2 + citeva intrari in Web.Config

Dar Scott o face mult mai bine , in

How to set an IIS Application or AppPool to use ASP.NET 3.5 rather than 2.0

Plus ca iti da diferentele intre Framework version si  CLR Version....

.NET | ASP.NET | programare
Thursday, May 08, 2008 10:52:31 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Tuesday, April 15, 2008


ASP.NET Dynamic Data Preview
A aparut - si e super!
E un generator de ASPX , in care poti modifica tot ce vrei ... si ce nu vrei.
E bazat pe LINQ  - asa ca merge doar cu SQL Server ...
Pentru generare pagini rapide eu super ... in sfirsit ceva care ma multumeste.
Va sfatuiesc sa incercati Wizard-ul din New -> WebSite ( faceti unul nou de fiecare data cind vreti sa incercati ceva...)

Instalare :

Downloadati si instalati .NET 3.5 SDK de aici
http://www.microsoft.com/downloads/thankyou.aspx?familyId=f26b1aa4-741a-433a-9be5-fa919850bdbf&displayLang=en#

Downloadati si instalati  ASP.NET Dynamic Data Preview de aici
http://code.msdn.microsoft.com/dynamicdata

Modificati in InstallDynamicData32bit.cmd
%ProgramFiles%\Microsoft SDKs\Windows\v60.A\bin\
cu
%ProgramFiles%\Microsoft SDKs\Windows\v6.1\bin\

si succes la customizare ...!



.NET | ASP.NET | LINQ | programare
Tuesday, April 15, 2008 2:08:56 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Sunday, March 09, 2008


Interceptarea erorilor in .NET 2.0
Am pornit o discutie pe RONUA, impins de nevoiea de a-mi consolida ideea de metoda de interceptare a erorilor
E interesant de urmarit (pentru cine stie .NET si nu numai ... ) intreaga discutie ( care inca nu s-a terminat...) .Mie mi-a placut replica lui Cryogenic



.NET | erori | programare
Sunday, March 09, 2008 3:29:51 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, March 04, 2008


Al patrulea pas : Importul datelor

 

Va sfatuim sa cititi partile anterioare

     Primul pas : instalarea software-ului free

    Al doilea pas : Analiza aplicatiei

    Al treilea pas : Structura Bazei de date

 

Sau tutorialul anterior despre .NET 2.0

        http://serviciipeweb.ro/iafblog/content/binary/tutorial.pdf

 

Vom importa datele din fisierul Excel in Baza de date. Daca am avea SQL Server Standard( sau mai mare) am putea importa direct din Excel in SQL Server.Este suficient sa facem click dreapta pe baza noastra de date , Tasks=> ImportData – ca in figura alaturata :

Dupa ce apasam, vom selecta la surse Excel:

Iar la destinatie serverul local de SQL Server

 

Cam asta ar fi, daca am avea SQL Server Standard.

Dar ,pentru ca avem SQL Server Express, nu avem o astfel de facilitate incorporata - asa ca va trebui sa ne descurcam importand datele cu un program in C#.

Vom creea tabele in SQL Server asemanatoare cu structura datelor din Excel. Vom crea tabelele asa cu am facut la pasul 3. De pilda tabela cu date despre cartile de copii va arata asa:

Acum vom importa datele. Va trebui sa facem citirea datelor in Excel si apoi scrierea lor in SQL Server.

Sa le luam pe rind:

Cream un nou proiect in C# , intitulat "ImportDate" de tip Consola in folder-ul C:\book3.

Linga toate "using" mai adaugam si un "using System.Data.OleDb;" ca sa putem citi din Excel si using System.Data.SqlClient pentru conectare la SQL Server.

O sa ne folosim de faptul ca DataAdapter stie sa faca modificari de date automat. Ne facem ca citim un DataTable din SQL Server, il umplem apoi cu datele de la Excel si ii spunem lui DataAdapter sa faca insert-urile pentru noi.

 

Deschidem o conexiune la SQL Server si citim datele din tabela "Excel_Copii":

 

Pentru citirea din Excel vom folosi driverul de OLEDB.Cream o conexiune la Excel si o sa citim datele din tabela "Copii".

Deschidem o conexiune la Excel

"Provider = \"Microsoft.Jet.OLEDB.4.0\";Data Source=\"C:\\book3\\carte.xls\";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";

(daca vreti sa stiti ce ISAM aveti , vedeti cu regedit cheia

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\ISAM Formats)

Deschidem o noua comanda, prin care selectam datele din Worksheetul "Copii"

oc.CommandText = "select * from [Copii$]";

 

(de remarcat sintaxa cu $ si paranteze drepte)

Cod complet:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.OleDb;

using System.Data.SqlClient;

using System.Data;

namespace ImportDate

{

class Program

{

static void Main(string[] args)

{

using (SqlConnection sco = new SqlConnection())

{

sco.ConnectionString = "Data Source=.\\sqlExpress;Integrated Security=true;Initial Catalog=Library";

 

sco.Open();

using (SqlDataAdapter sda = new SqlDataAdapter("select * from Excel_Copii", sco))

{

// construct insert

if (sda.InsertCommand == null)

{

SqlCommandBuilder scb = new SqlCommandBuilder(sda);

sda.InsertCommand = scb.GetInsertCommand(true);

}

System.Data.DataTable dtTransfer = new System.Data.DataTable();

sda.Fill(dtTransfer);

 

 

 

 

using (OleDbConnection odc = new OleDbConnection())

{

odc.ConnectionString = "Provider = \"Microsoft.Jet.OLEDB.4.0\";Data Source=\"C:\\book3\\carte.xls\";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";

odc.Open();

using (OleDbCommand oc = new OleDbCommand())

{

oc.CommandType = System.Data.CommandType.Text;

oc.CommandText = "select * from [Copii$]";

oc.Connection = odc;

//fill data table with Excel data

System.Data.DataTable dtExcel = new System.Data.DataTable();

using (OleDbDataReader sr = oc.ExecuteReader())

{

dtExcel.Load(sr);

}

 

// transfer rows

foreach (DataRow dr in dtExcel.Rows)

{

 

DataRow drNew = dtTransfer.NewRow();

drNew.ItemArray = dr.ItemArray;

dtTransfer.Rows.Add(drNew);

}

}

 

 

sda.Update(dtTransfer);

}

}

}

}

}

}

 

La fel se importa si datele din tabela de SF.

Acum este cazul sa importam datele in tabele.

Mai intii, cea de autori.

Va trebui sa luam autorii din toate tabelele .

 

SELECT

[Autor1] as autor

FROM [Library].[dbo].[Excel_Copii]

union

select [Autor2]

FROM [Library].[dbo].[Excel_Copii]

UNION

SELECT

[Autor1] as autor

FROM [Library].[dbo].[Excel_SF]

union

select [Autor2]

FROM [Library].[dbo].[Excel_SF]

 

Observam urmatoarele date:

NULL

ISPIRESCU Petre

Andersen

George Lucas

Ion Creanga

Isaac Asimov

Petre Ispirescu

 

 

Va trebui sa facem 2 lucruri:

  1. Consolidarea datelor – in definitiv, Petre Ispirescu = ISPIRESCU Petre
  2. Inserarea in tabela Person si Tabela Author

Punctul 1 este destul de usor de facut cu un update ...

update Excel_Copii set Autor1= 'Petre Ispirescu' where Autor1 = ' ISPIRESCU Petre'

Punctul 2 il vom face inserind in tabela de persoane si pe urma in tabela de Autori

INSERT INTO [Library].[dbo].[Person]

([FirstNamePerson],[LastNamePerson]

)

 

select autor,'' from

(

SELECT

[Autor1] as autor

FROM [Library].[dbo].[Excel_Copii]

union

select [Autor2]

FROM [Library].[dbo].[Excel_Copii]

UNION

SELECT

[Autor1] as autor

FROM [Library].[dbo].[Excel_SF]

union

select [Autor2]

FROM [Library].[dbo].[Excel_SF]

 

) a where a.autor is not null

Acum separam nume de prenume:

UPDATE

    Person

SET

    FirstNamePerson = substring(FirstNamePerson,1,charindex(' ' ,FirstNamePerson)-1),

    LastNamePerson = substring(FirstNamePerson,charindex(' ' ,FirstNamePerson)+1,100)

WHERE charindex(' ' ,FirstNamePerson)>0

Rezultatul este:

IDPerson    FirstNamePerson    LastNamePerson    DateOfBirthPerson

2    Andersen        NULL

3    George    Lucas    NULL

4    Ion    Creanga    NULL

5    Isaac    Asimov     NULL

6    Petre    Ispirescu    NULL

 

Acum le vom insera in tabela de Autori:

INSERT INTO

    [Author]

([IDPerson]

)

SELECT IDPerson FROM Person

 

La fel inseram cartile si editurile..

Acum trebuie sa refacem legaturile, de pilda, intre autori si carti

    INSERT INTO [Book_Author]

([IDBook]

,[IDAuthor])

 

select IDBOOK,IDAuthor from Book b

inner join Excel_SF excel

inner join Person p on excel.Autor1 = p.FirstNamePerson + ' ' + p.LastNamePerson

inner join Author a on p.IDPerson = a.IDPerson

on excel.Titlu = b.Title

 

La fel si pentru carti cu edituri :

update book

set IDPrintingHouse =

p.IDPrintingHouse from Book b

inner join Excel_SF excel

inner join PrintingHouse p on p.NamePrintingHouse = excel.Editura

on excel.Titlu = b.Title

Ramine la latitudinea cititorului exercitiul cu celelalte update-uri.

Backupul la BD il gasiti in folder-ul database si se numeste "lib_date_importExcel.bak" . Puteti face restore.

De citit:

  1. Primul pas : instalarea software-ului free , in care downloadati VC# Express si SQL Server Express
  2. Stringuri de conexiune pentru orice baza de date : www.connectionstrings.com

 

Surse

Tutorial PDF

        

 

.NET | programare | tutoriale
Tuesday, March 04, 2008 10:02:54 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, February 26, 2008


Al treilea pas : Structura Bazei de date

 

Va sfatuim sa cititi partile anterioare

     Primul pas : instalarea software-ului free

    Al doilea pas : Analiza aplicatiei

 

Sau tutorialul anterior despre .NET 2.0

        http://serviciipeweb.ro/iafblog/content/binary/tutorial.pdf

 

Facind deja (minima) analiza a aplicatiei, putem acum sa vorbimdespre structura bazei de date. Vom face direct o baza de date relationala in cea de a treia forma normala. Pentru aceasta pornim SQL Server Management Studio Express,ne logam la serverul local (./ sau ./sqlexpress, depinde cum ati numit instanta) prin Windows authentication (cea mai simpla metoda) si click dreapta pe Databases => New Database

Numele pe care o sa i-l dam o sa fie "Library" si o sa concepem tabelele ca fiind replica exacta a obiectelor.

Vom crea tabelele direct din "Database Diagrams" Raspundem cu "Yes" la intrebarea despre "Diagram support"

 

Si cream o diagrama noua, numita "Library".Click dreapta, "New Table", "Person". Adaugam coloanele ca in figura, cu mentiunea ca "IDPerson" o facem "Identity" si Primary Key

 

Acum vom creea tabela Author – aceasta va contine o IDPerson – evidentiere a faptului ca orice Autor este si o persoana. La fel, IDAuthor este PK si Identity

Vom"trage" IDPerson din tabela Author peste IDPerson din tabela "Person", obtinind in acest fel legatura intre Autor si Persoana.

 

La fel si pentru celelalte tabele.

In final vom avea urmatoare structura :

Vom face un backup al Bazei de date ca in figura:

Puteti crea BD singuri sau puteti face "restore" la ea dupa acest backup , numit lib_empty.bak

Surse aici

http://serviciipeweb.ro/iafblog/content/binary/net3/20080226.zip

Acest tutorial in intregime aici

Data viitoare vom importa datele din Excel in SQL Server.

De citit:

  1. Despre cele 3 forme normale : http://en.wikipedia.org/wiki/Database_normalization
  2. Identity in SQL Server : http://www.sqlteam.com/article/understanding-identity-columns
  3. PK, FK : http://en.wikipedia.org/wiki/Foreign_key
  4. Moduri de a defini mostenirea in cadrul BD : http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/09/30/how-to-model-inheritance-in-databases.aspx

     

 

 

 

.NET | programare | tutoriale
Tuesday, February 26, 2008 9:58:18 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Wednesday, February 20, 2008


Al doilea pas : Analiza aplicatiei

 

Va sfatuim sa cititi prima parte, Primul pas : instalarea software-ului free

Sau tutorialul anterior despre .NET 2.0         http://serviciipeweb.ro/iafblog/content/binary/tutorial.pdf

 

Aplicatia pe care o sa o facem este una de gestionare(management, pe stil nou) a cartilor dintr-o biblioteca publica. Presupunem ca biblioteca deja isi tine o evident a cartilor intr-un Excel cu o multitudine de sheet-uri, cam de aceasta forma

Un sheet, numit "Copii" care contine carti pentru copii,cu urmatoarele date:

 

Titlu 

Autor1 

Autor2 

editura 

Pret 

Imprumutata de  

Data imprumutului 

Craiasa zapezii 

Andersen

 

Teora 

3 

Ignat Andrei 

15/01/2008 

GREUCEANU SI ALTE POVESTI  

ISPIRESCU Petre 

 

All 

5 

  

Capra cu trei iezi  

Ion Creanga 

 

Polirom 

2 

  

  

Ursul păcălit de vulpe  

Ion Creanga 

 

All 

5 

  

Zana muntilor  

Petre Ispirescu 

 

Teora 

2 

  

  

    

Alt sheet, numit SF, cu urmatoarele date

Titlu 

Autor1 

Autor2 

Editura 

Pret 

Imprumutata de  

Data imprumutului 

Caverne de otel  

Isaac Asimov  

Teora 

15 

Ignat Andrei

15/01/2008 

Fundatia  

Isaac Asimov  

Teora 

31 

  

Fundatia si imperiul  

Isaac Asimov  

Teora 

23 

  

Fundatia si Pamantul  

Isaac Asimov  

Teora 

21 

  

Inainte de fundatie  

Isaac Asimov  

Teora 

13 

  

RAZBOIUL STELELOR 

George Lucas 

Polirom 

54 

  

 

 

Pare destul de clar , nu ? Fiecare carte are cite o fisa in carte, care spuen cine a imprumutat-o si cind.

Puteti downloada fisierul Excel de la adresa http://serviciipeweb.ro/iafblog/content/binary/carte.xls

Daca nu aveti Excel (?) , puteti downloada Excel Viewer

Acum vom face o mica analiza a datelor existente , pentru ca cerintele aplicatiei, ca de obicei, sunt vagi : "sa faca o cautare intre datele existente si sa reproduca procesul existent..."

E clar ca avem de a face cu urmatoarele obiecte:

Editura – ca atribute: nume, site, email

Persoana – nume, prenume, data nasterii

Autor – este o Persoana care in plus are ca atribut – site,(una sau mai multe) Carti publicate

Bibliotecare – este o Persoana cu drepturi de modificare Carti/Edituri/Autori/Setari

Client – Este o Persoana care are dreptul sa imprumute un numar(Setare) de Carti pe o perioada data (Setare)

Carti – ca atribute : Nume, data aparitiei, (publicata de ) Editura, (unul sau mai multi) Autori, ISBN, pret

Setari – Numar de carti imprumutate, Perioada imprumutului

 

Nu voi lua in considerare multe alte lucruri, ca de pilda faptul ca un client pierde o carte sau ca preturile pot fi modifiacte in timp ...Ar complica in mod inutil aplicatia – care nu vrea sa fie o aplicatie completa, ci doar un demo.

Data viitoare o sa facem designul Bazei de date.

Surse

 

De citit:

  1. Despre Object oriented http://en.wikipedia.org/wiki/Object_oriented

     

     

 

.NET | programare | tutoriale
Wednesday, February 20, 2008 4:52:53 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, February 05, 2008


Programare in .NET 3.5

Incep din nou seria de tutorial despre programare in .NET – de data aceasta .Net 3.5

Primul pas : instalarea software-ului free

Acest pas se efectuează o singura date pe PC. Este vorba despre instalarea server-ului de Web , precum si a Visual Studio Express ca si unealta de dezvoltare. Este cel mai lung pas, dar, precum am spus, se efectuează o singura data.

 

Să începem: ai Windows (XP, de preferinţă) si ne asiguram ca ai server-ul de Web (Internet Information Services – IIS de acum înainte) pe maşină .Pentru aceasta te duci in "Control panel" => "Administrative Tools" si verificaţi ca există.

 

    Daca nu exista, mergeţi înapoi la "Control Panel", apăsaţi pe "Add or Remove programs" si apăsaţi pe "Add/Remove Windows Components". Bifaţi IIS ca in imagine si daţi "Next"( asiguraţi-vă ca aveţi CD-ul de instalare Windows prin apropiere)

 

 

Bun – acum o sa instalam VS 2008 Express. Acesta este free si îl puteţi descărca de la adresa

http://www.microsoft.com/express/download/offline.aspx. Acolo gasiţi o imagine ISO pe care o puteti downloada . O puteţi vedea cu ISObuster, Daemon Tools or Virtual CloneDrive ( căutaţi-le pe google pentru linkuri de download) sau cu un program făcut de MS, Virtual CD-ROM Control Panel for Windows XP care poate fi downloadat de la adresa:

http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe

( da, ştiu, e o adresa scurta)

De asemenea, instalati SQL Server Express Edition with Advanced Services SP2 de la adresa http://www.microsoft.com/express/sql/download/default.aspx

Si tool-ul de administrare grafica, numit Microsoft SQL Server 2005 Express Edition Toolkit, de la aceeasi adresa http://www.microsoft.com/express/sql/download/default.aspx

Download pdf de aici:

http://serviciipeweb.ro/iafblog/content/binary/tutorialnet3.pdf

.NET | LINQ | programare | tutoriale
Tuesday, February 05, 2008 11:28:49 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, January 29, 2008


linq si defered execution
oarte interesante rezultatele - si cum te poti insela

The following sample shows how query execution is deferred until the query is enumerated at a foreach statement.

public void Linq99() {
// Sequence operators form first-class queries that
// are not executed until you enumerate over them.

int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

int i = 0;
var q =
from n in numbers
select ++i;

Console.WriteLine("i = {0}", i);
// Note, the local variable 'i' is not incremented
// until each element is evaluated (as a side-effect):
foreach (var v in q) {
Console.WriteLine("v = {0}, i = {1}", v, i);
}
}


Ce valoare are i cind se executa Console.WriteLine("i = {0}", i);  ? Raspuns : 0!

Rezultat :

i = 0
v = 1, i = 1
v = 2, i = 2
v = 3, i = 3
v = 4, i = 4
v = 5, i = 5
v = 6, i = 6
v = 7, i = 7
v = 8, i = 8
v = 9, i = 9
v = 10, i = 10

Al doilea exemplu :
The following sample shows how queries can be executed immediately with operators such as ToList().

public void Linq100() {
// Methods like ToList() cause the query to be
// executed immediately, caching the results.

int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

int i = 0;
var q = (
from n in numbers
select ++i )
.ToList();

Console.WriteLine("i = {0}", i);
// The local variable i has already been fully
// incremented before we iterate the results:
foreach (var v in q) {
Console.WriteLine("v = {0}, i = {1}", v, i);
}
}


Ce valoare are i cind se executa Console.WriteLine("i = {0}", i);  ? Raspuns : 10!
Rezultat :
i = 10
v = 1, i = 10
v = 2, i = 10
v = 3, i = 10
v = 4, i = 10
v = 5, i = 10
v = 6, i = 10
v = 7, i = 10
v = 8, i = 10
v = 9, i = 10
v = 10, i = 10

De asemenea m-a impresionat CreateDatabase();  - desi cred ca era mai impresionant pe generics...
Abia astept versiunea pentru access - sa vezi atunci export import...

La fel , m-a impresionat inheritance cu ajutorul lui [InheritanceMapping(Code="Shipper", Type=typeof(ShipperContact))] si 
[Column(Storage="_ContactType", DbType="NVarChar(50)", IsDiscriminator=true)]

public void LinqToSqlInheritance03()
{
    var cons = from c in db.Contacts
               where c is ShipperContact
               select c;

    ObjectDumper.Write(cons, 0);
}

.NET | LINQ | programare
Tuesday, January 29, 2008 7:59:16 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, January 22, 2008


Linq si Dynamic Query
Am downloadat sample-urile de C# si, cu generarea automata in cap, m-am apucat de Dynamic Query.
Exemplul e relativ bun:

Northwind db = new Northwind(connString);
db.Log = Console.Out;
Console.WriteLine("before");
var query =
db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("New(CompanyName as Name, Phone)");


Console.WriteLine(query);
Console.ReadLine();


Dar cum vad rezultatele ?
Prima incercare a fost simpla:

foreach (var c in query)
{
Console.WriteLine(c.ToString());
}


Ma rog... destul de bine... Dar pentru o aplicatie adevarata as avea nevoie sa vad numele si telefonul...

Asa ca m-am dus in DynamicClass si am adaugat:

private PropertyInfo[] _pi;
public PropertyInfo[] Properties
{
get
{
if (_pi == null)
{
_pi = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
}
return _pi;
}
}
public object GetValue(string PropName)
{
PropertyInfo pi= Properties.Single<PropertyInfo>(c => c.Name == PropName);
return pi.GetValue(this, null);
}

In felul acesta am putut scrie in main:

Northwind db = new Northwind(connString);
db.Log = Console.Out;
Console.WriteLine("before");
var query =
db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("New(CompanyName as Name, Phone)");

Console.WriteLine("after");
foreach (DynamicClass c in query)
{

Console.WriteLine(c.GetValue("Name"));
Console.WriteLine(c.GetValue("Phone"));
Console.WriteLine("-------------------");
}
Console.WriteLine(query);
Console.ReadLine();



Problema rezolvata....
Ati facut Linq ? Si, daca da, cum ati (fi) rezolvat problema ?

.NET | LINQ | programare
Tuesday, January 22, 2008 5:56:55 AM (GMT Standard Time, UTC+00:00)  #    Comments [3]  |  Trackback


Saturday, December 22, 2007


Late binding Outlook - VB.NET versus C#
Inca o data, cind e vorba de COM, VB este mult mai bun decit C#.
Incercam sa creez un email cu Late binding in C#:

Type app = Type.GetTypeFromProgID("Outlook.Application");
object oApp = Activator.CreateInstance(app);
object oNameSpace = app.GetMethod("GetNamespace").Invoke(oApp, new object[] { "MAPI" });
oNameSpace.GetType().GetMethod("Logon").Invoke(oNameSpace, new object[] { Type.Missing, Type.Missing, Type.Missing, Type.Missing});


Object mail = oApp.GetType().GetMethod("CreateItem").Invoke(oApp, new object[1] { 0 });
Type t = mail.GetType();
t.GetMethod("Display").Invoke(mail, new object[] { false });



Eroare....tipul t nu are metoda Display ...

Aproape acelasi cod, mai usor scris , in VB.NET

Dim app As Type = Type.GetTypeFromProgID("Outlook.Application")
Dim oApp As Object = Activator.CreateInstance(app)
Dim oNameSpace As Object = oApp.GetNamespace("MAPI")
oNameSpace.Logon()
Dim mail As Object = oApp.CreateItem(0)
mail.Display(False)


Normal ca merge ?

Diferentele intre ele dpdv IL ? Daca va uitati cu reflector la ceea ce genereaza VB.NET, o sa vedeti ca nu e pur si simplu Reflection chior - ci tot felul de incercari   in speranta de  a da peste metoda respectiva....


Concluzie:
Daca aveti de a  face cu COM(Office), faceti un DLL de VB.NET -iesiti mai ieftin si mai rapid si mai curat ( e.g., eliminarea Type.Missing)


.NET | programare | VB.NET versus C#
Saturday, December 22, 2007 5:03:15 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Wednesday, December 05, 2007


Developing Time-Oriented Database Applications in SQL
Am citit de curind Developing Time-Oriented Database Applications in SQL (Morgan Kaufmann Series in Data Management Systems)


O carte superba! Nu stiu cum am trait pina acum fara ea ! De fapt, mint: stiu cum am trait -  la intimplare! Are acuratete, SQL clar si concizie despre cum ar trebui dezvoltate BD time aware.
De citit NEAPARAT!Iar eu, cu defectul meu de a trece mai departe chiar daca nu inteleg, va trebui sa o recitesc!

Un singur repros : prea crede in SQL 3... dar, cit priveste SQL 92 si claritatea expunerii, are nota 10 +


Se poate downloada free de aici :
http://www.cs.arizona.edu/people/rts/tdbbook.pdf


.NET | carti | programare | sql
Wednesday, December 05, 2007 11:49:22 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, December 04, 2007


curs valutar si twitter
Asa cum am spus intr-un  post mai vechi, am facut ca sa trimit notificari de curs valutar BNR prin contul de la twitter
Am gasit un proiectel gata facut pentru asa ceva, yedda twitter , pentru care am scris un simplu cod, de genul :

Yedda.Twitter t = new Yedda.Twitter();
t.UpdateAsJSON("user_email", "password", "text");

Destul de usor - si are si codul sursa in el ( daca vreti sa functioneze pe 1.1, inlocuiti string.IsNullOrEmpty cu o metoda proprie)

Downsize:
    Nu se poate abona doar la anumite cursuri - de ex., doar la EUR si USD.

Dar ca realizare, imi place!


Ca sa va puteti urmari cursul valutar prin SMS cu ajutorul twitter, faceti urmatorii pasi:

1. Inregistrati-va/logati-va la http://twitter.com/

2. La pagina http://twitter.com/devices
adaugati telefonul dvoastra ( daca aveti in RO 07xx..., puneti +407xx...)

3. O sa va spuna sa trimiteti SMS cu un anume mesaj la alt numar de telefon ca sa puteti activa telefonul respectiv. Trimiteti si va vine SMS de confirmare a activarii numarului

4. Adaugati cursval  , cautindu-l la adresa http://twitter.com/invitations

5. La pagina http://twitter.com/<nume_login_twitter>/friends dati click pe persoana respectiva si puneti notifications la on.

That's all, folks!


.NET | programare | twitter
Tuesday, December 04, 2007 8:47:32 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, December 02, 2007


un alt proiectel - using
De mult mi-am dorit sa il pun pe codeplex - si, iata, am reusit
http://codeplex.com/UsingLib

La ce e bun? 2 lucruri, deocamdata:
1. Pune cursor hourglass pentru evenimente pe forma si restaurare automata in momentul in care se termina evenimentul
2. Logare (aproape) automata - cu log4net - pentru o functie.

Amindoua - utilizand IDisposable  si using - astfel incit sa nu fie necesar sa tot try-catch-uiesc...

Sunt facute in C# si nu in VB.NET din un motiv simplu : din cauza primului meu sef pe .NET . Cind a auzit ca vreau sa scriu in VB.NET( venind eu dinspre VB6)  l-a apucat:"Sigur, sa intelegi numai tu ce scrii..." . Asa ca de atunci gindesc in C#. Si, in afara de case sensitivity si callbyname , nu am ce sa ii reprosez...

.NET | programare
Sunday, December 02, 2007 9:09:14 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Wednesday, November 21, 2007


sql exception si sysmessages
Aveam o cheie unica tip string pe tabela - si vroiam sa transform eroarea de SQL Exception intr-una proprie(sa ii spun user-ului ca este duplicat)
Imi dadea numarul erorii- dar nu stiam daca e unic- si daca e relevant...
Am descoperit ca este toate mesajele de eroare din SQL Server sunt in sysmessages - super convenabil ca sa le poti citi.
Acum, daca pastreaza compatibilitatea intre versiuni de SQL Server, deja este alta poveste - desi cred ca da...

.NET | programare | sql
Wednesday, November 21, 2007 1:15:54 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Friday, November 09, 2007


instalarea .net 2.0 si control panel
Pentru un prieten, caruia trebuia sa ii mearga un control Windows Forms .NET 2.0 in IE( nu intrebati!) i-am facut un proof of concept si i-am spus ce trebuie sa configureze la securitate in Control Panel=> Administrative Tools=>Microsoft .NET Framework 2.0 Configuration

M-a intrebat: Daca nu am .NET 2.0, ce fac?

Simplu, raspund eu : iei .NET redistributable de aici
http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5&displaylang=en

Instaleaza, restarteaza, si ma contacteaza :dar nu am Microsoft .NET Framework 2.0 Configuration !

Ma uit cu Remote Desktop - da, instalase .NET 2.0. Da, nu avea Microsoft .NET Framework 2.0 Configuration !

Concluzia:
Daca vreti si sa il configurati, instalati si SDK
http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec&DisplayLang=en

Destul de neplacut...

Mai multe amanunte aici
http://blogs.msdn.com/astebner/archive/2005/12/19/505734.aspx

si un hack aici (nemaivorbind ca avem si command line  caspol)


.NET | programare
Friday, November 09, 2007 8:13:23 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, June 17, 2007


Dezamagit de MSDN
Daca la un programator obisnuit este ok sa vad ca valoare default "fish" de la MSDN ma astept la mai mult.
Am citit articolul intitulat Write Code Once For Both Mobile And Desktop Apps si ce gasesc acolo ?

Vrea sa demonstreze ca pentru Pocket PC si pentru Desktop nu se poate chema la fel calea catre calc.exe. Si da urmatorul cod:
private void mnuCalc_Click(
object sender, EventArgs e)
{
string pth;
if (Environment.OSVersion.Platform == PlatformID.WinCE)
{
pth = @”\Windows\calc.exe”;
}
else
{
pth = @”c:\Windows\system32\calc.exe”;
}
Process.Start(pth, null);
}



totusi , cind exista cel putin aceste 2 optiuni
  1. System.Environment.GetFolderPath(Environment.SpecialFolder.System)
  2. System.Environment.GetEnvironmentVariable("windir")

si cind nimeni nu mai hardcodeaza directorul de instalare al Windows de mult *in VB6 foloseam api la greu) cum poti sa scrii asa ceva? Si cum de trece de editorii de MSDN?
			

.NET | inconsistente | programare
Sunday, June 17, 2007 9:22:30 PM (GMT Daylight Time, UTC+01:00)  #    Comments [1]  |  Trackback


Thursday, June 14, 2007


CurrentCulture versus CurrentUICulture
De la Michael Kaplan ( via RONUA prin postul lui Ovidiu ) am inteles in sfirsit diferenta dintre CurrentUICulture  si CurrentCulture :
prima se refera in special la RESURSE (localizare / internationalizare), iar a doua la regional settings pentru user....

O metoda usoara de amintire a acestor fapte este sa te gindesti la CurrentUICulture  ca la  CurrentResourceCulture ....

.NET | programare
Thursday, June 14, 2007 7:16:50 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Saturday, May 26, 2007


CHm2Word , VB.NET vs C# si codeplex
Am tot primit fisiere CHM si PDF cu carti de programare (si tin sa multumesc celor care mi le-au trimis).
PDF era OK... se puteau tipari daca vroiam. Insa CHM era o problema.Am cautat pe net sa gasesc o transformare CHM in altceva... si am cautat free... insa nu am gasit.

Asa ca am decis sa fac un programel in .NET care sa transforme din CHM in Word.Foloseste faptul ca word-ul este pe masina locala.

E facut in VB.NET si nu in C# din  cauza ca:
    1. Nu vroiam sa fac referinta la Word, ci sa folosesc orice instanta de Word (2000,2003,2007) existenta pe masina- ma rog, aici nu e mare deosebire, insa ajungem la punctul 2
    2. Sa imi fie cit mai usor sa apelez functiile COM din Word. Aici sunt 2 diferente:  
          a) InC# pentru parametrii optionali scriu la Type.Missing de imi vine rau- in VB.NET nu
          b)In C# utilizez reflection pentru a accesa metode.In VB.NET pun . si scriu metoda(se chema late binding)

Daca socotiti ca va foloseste, il gasiti aici
http://www.codeplex.com/chm2word

Acum, codeplex are un utilitar care permite uploadarea proiectelor pe site.
M-am cam fript cu el... si nu am gasit cum sa sterg primele versiuni ... ceea ce e si normal...

Dar , ca sfaturi pentru cei care vor sa faca asa ceva (adica au pus un proiect deja pe codeplex )si au TOT proiectul intr-un folder:
1. Daca aveti proiectul in radacina, mutati-l intr-un altul ( de ex. proiecte)
2. Va pozitionati in command line astfel incit la comanda dir folder-ul proiectului sa apara( adica un director mai sus - DAR CARE SA NU FIE RADACINA)
3. cpc checkout <numeproiect>
4. cpc add <folder_proiect> /e  ( adica recursive)
5. cpc commit <numeproiect>

Succes!

.NET | programare | proiecte
Saturday, May 26, 2007 10:44:17 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Tuesday, May 08, 2007


teste automate si baza de date SQL Server 2005
Cea mai grea provocare pe care am avut-o cind incercam sa aplic Extreme Programming era sa refac datele din BD. Si am incercat tot felul de tot felul:import/export din XML, dbf, access. Totul era mincator de timp si de resurse ...si nesigur

Pina deunazi, cind m-am gindit la modelul ASP.NET : se ataseaza o BD la runtime!( vezi ce se creeaza in web.config cind , de pilda,faci management de user-i din consola de configurare IIS)


Asa ca - de ce nu as face acelasi lucru si pentru teste?
Si am descoperit ca sintaxa :
Data Source=<Numeinstanta2005>;Integrated Security=True;AttachDbFileName=<cale catre fisierul mdf;Initial Catalog=<numele bazei de date>"


URAAAAAAA!

.NET | programare | sql | Extreme Programming
Tuesday, May 08, 2007 10:05:54 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Saturday, April 28, 2007


Programarea in .NET - partea a 17-a Rapoarte in ASP.NET –Windows Forms

Haideti sa repetam ceea ce am facut in ASP.NET pentru WindowsForms

Deschideti Book.sln, adaugati o noua forma in proiect(frmPublisherPrint.cs) si trageti ReportViewer in forma.(Daca nu il gasiti, click dreapta in Toolbox, alegeti “choose items” , cautati ReportViewer din namespace-ul Microsoft.Reporting.WinForms si selectati-l

 

 

 

Adaugam raportul existent prin click dreapta pe BookWin

 

Va duceti in BookWeb, alegeti din casuta “Files of type” ultima selectie “All files” si selectati rptPublisher.rdlc.

Acum click pe el si in fereastra de proprietati alegeti la “Copy to output directory “ “Copy always”

 

 

 

 

Bun – acum au ramas 3 lucruri de facut : vizualizarea formei ca actiune, legarea controlului de raportul existent si codul de incarcare a datelor in raport.

 

Pentru vizualizarea formei ca actiune adaugati un buton btnPrint in frmPublisherList iar pe eveniment scrieti urmatorul cod:

private void btnPrint_Click(object sender, EventArgs e)

{

frmPublisherPrint p = new frmPublisherPrint();

p.ShowDialog(this);

}

 

Pentru legarea controlului vom seta la proprietati calea catre raport(presupunem ca se va afla in acelasi folder) si processing mode la local

 

Ultimul lucru de facut – incarcarea colectiei pe evenimentul de load :

rivate void frmPublisherPrint_Load(object sender, EventArgs e)

{

BookObjects.ColPublisher publishers = new BookObjects.ColPublisher();

publishers.Load();

MessageBox.Show(""+publishers.Count);

ReportDataSource rds = new ReportDataSource("DataSet1_Publisher", publishers);

rptPublisher.ProcessingMode = ProcessingMode.Local;

rptPublisher.LocalReport.DataSources.Clear();

rptPublisher.LocalReport.DataSources.Add(rds);

rptPublisher.LocalReport.Refresh();

rptPublisher.RefreshReport();

}

( exact acelasi cod ca la Web, in afara liniei :

 

Ea previne cazul( des intilnit) in care editorul IDE adauga , cu de la sine putere, un ReportDataSource .

Ceea ce se va infatisa va fi:

 

 

 

 

 

Ce mai e de facut

1)frmPublisherPrint sa nu mai afiseze ce vrea ea - ci sa primeasca un argument(in constructor, de exemplu) care sa spun ce lista de publisher-i are de afisat

2) Avind in vedere ca rapoartele sunt aceleasi pentru Windows si Web , ar fi interesant de facut un dll care sa intoarca raport – ul cerut

 

.NET | programare | tutoriale
Saturday, April 28, 2007 11:12:44 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Thursday, April 26, 2007


cum sa integrezi Visual Source Safe cu Visual Studio
Daca ati instalat VS si nu il vedeti pe VSS la tools=> options    => Source control => plugin selection , e suficient sa inregistrati SSSCC.DLL din <Program Files>\Microsoft Visual Studio\VSS\netsetup.x86\VSS\win32
M-am chinuit 3 ore sa gasesc asta... si m-am gindit sa mai usurez munca cuiva...

.NET | programare | vss
Thursday, April 26, 2007 3:57:37 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Sunday, April 22, 2007


PROGRAMAREA IN .NET - PARTEA A 16-A RAPOARTE IN ASP.NET

Orice aplicatie trebuie sa aiba posibilitatea de a tipari datele. Pentru aceasta in VS2005 Express se poate folosi componenta Report Viewer care e free si se poate downloada de la http://www.gotreportviewer.com.

Dupa ce o instalati, o sa aveti in toolbox urmatoarea componenta:

 

 

Acum adaugam un raport care sa fie afisat de catre aplicatie – deschidem aplicatia Web si adaugam un nou item de tipul Report si il numim rptPublisher.rdlc :

 

 

Acum adaugam un nou datasource apasand pe Add New DataSource

 

 

In ecranul urmator apasam pe NewConnection si selectam baza noastra de date:

 

Putem salva conexiunea in Web.Config(desi o mai avem) si apasam Next. Pe urmatorul ecran lasam selectat “Use SQL Statements” si iarasi Next. Acum scriem codul pentru SQL:

 

SELECT IDPublisher, NamePublisher, SitePublisher

FROM Publisher

 

si iarasi Next pina se termina ( sau direct Finish).

 

Acum in WebSite DataSource ne-a aparut dataset-ul care contine Publisher

 

 

Ne ducem pe Toolbox si tragem pe rptPublisher.rdlc un Table

Ne intoarcem pe WebSite DataSources si tragem Name Publisher pe detaliu:

 

 

Acum sa verificam

Cream o noua pagina aspx, frmPublisherReport.aspx si scriem urmatorul cod(sau tragem controlul de ReportViewer si ii spunem care e raportul)

<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisherReport.aspx.cs" Inherits="frmPublisherReport" Title="Report Publisher" %>

 

<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

<rsweb:ReportViewer ID="rptPublisher" runat="server">

<LocalReport ReportPath="rptPublisher.rdlc">

</LocalReport>

</rsweb:ReportViewer>

</asp:Content>

 

In codul C# punem urmatoarele linii :

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using Microsoft.Reporting.WebForms;

 

public partial class frmPublisherReport : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

BookObjects.ColPublisher publishers = new BookObjects.ColPublisher();

publishers.Load();

ReportDataSource rds = new ReportDataSource("DataSet1_Publisher",publishers);

rptPublisher.ProcessingMode = ProcessingMode.Local;

rptPublisher.LocalReport.DataSources.Add(rds);

rptPublisher.LocalReport.Refresh();

 

}

 

}

 

Si modificam fisierul rdlc deschizindu-l cu notepad-ul si scriind urmatoarele:

<?xml version="1.0" encoding="utf-8"?>

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">

<DataSources>

<DataSource Name="BookConnectionString">

<ConnectionProperties>

<ConnectString />

<DataProvider>SQL</DataProvider>

</ConnectionProperties>

<rd:DataSourceID>c649d533-64c3-42b6-9805-19adbfccd468</rd:DataSourceID>

</DataSource>

</DataSources>

<BottomMargin>1in</BottomMargin>

<RightMargin>1in</RightMargin>

<rd:DrawGrid>true</rd:DrawGrid>

<InteractiveWidth>8.5in</InteractiveWidth>

<rd:SnapToGrid>true</rd:SnapToGrid>

<Body>

<ReportItems>

<Table Name="table1">

<Footer>

<TableRows>

<TableRow>

<TableCells>

<TableCell>

<ReportItems>

<Textbox Name="textbox7">

<rd:DefaultName>textbox7</rd:DefaultName>

<ZIndex>1</ZIndex>

<Style>

<PaddingLeft>2pt</PaddingLeft>

<PaddingBottom>2pt</PaddingBottom>

<PaddingRight>2pt</PaddingRight>

<PaddingTop>2pt</PaddingTop>

</Style>

<CanGrow>true</CanGrow>

<Value />

</Textbox>

</ReportItems>

</TableCell>

</TableCells>

<Height>0.45833in</Height>

</TableRow>

</TableRows>

</Footer>

<Left>0.5in</Left>

<DataSetName>DataSet1_Publisher</DataSetName>

<Top>0.25in</Top>

<Width>6.5in</Width>

<Details>

<TableRows>

<TableRow>

<TableCells>

<TableCell>

<ReportItems>

<Textbox Name="txtName">

<rd:DefaultName>Name</rd:DefaultName>

<Style>

<PaddingLeft>2pt</PaddingLeft>

<PaddingBottom>2pt</PaddingBottom>

<PaddingRight>2pt</PaddingRight>

<PaddingTop>2pt</PaddingTop>

</Style>

<CanGrow>true</CanGrow>

<Value>=Fields!Name.Value</Value>

</Textbox>

</ReportItems>

</TableCell>

</TableCells>

<Height>0.45833in</Height>

</TableRow>

</TableRows>

</Details>

<Header>

<TableRows>

<TableRow>

<TableCells>

<TableCell>

<ReportItems>

<Textbox Name="textbox1">

<rd:DefaultName>textbox1</rd:DefaultName>

<ZIndex>2</ZIndex>

<Style>

<PaddingLeft>2pt</PaddingLeft>

<PaddingBottom>2pt</PaddingBottom>

<PaddingRight>2pt</PaddingRight>

<PaddingTop>2pt</PaddingTop>

</Style>

<CanGrow>true</CanGrow>

<Value>Name</Value>

</Textbox>

</ReportItems>

</TableCell>

</TableCells>

<Height>0.45833in</Height>

</TableRow>

</TableRows>

</Header>

<TableColumns>

<TableColumn>

<Width>6.5in</Width>

</TableColumn>

</TableColumns>

<Height>1.375in</Height>

</Table>

</ReportItems>

<Height>2in</Height>

</Body>

<rd:ReportID>9f0247a8-15fe-4ef9-962e-c4c670524163</rd:ReportID>

<LeftMargin>1in</LeftMargin>

<DataSets>

<DataSet Name="DataSet1_Publisher">

<rd:DataSetInfo>

<rd:ObjectDataSourceType>Publisher</rd:ObjectDataSourceType>

<rd:TableName>Publisher</rd:TableName>

</rd:DataSetInfo>

<Query>

<rd:UseGenericDesigner>true</rd:UseGenericDesigner>

<CommandText />

<DataSourceName>BookConnectionString</DataSourceName>

</Query>

<Fields>

<Field Name="IDPublisher">

<rd:TypeName>System.Int32</rd:TypeName>

<DataField>IDPublisher</DataField>

</Field>

<Field Name="Name">

<rd:TypeName>System.String</rd:TypeName>

<DataField>Name</DataField>

</Field>

<Field Name="Site">

<rd:TypeName>System.String</rd:TypeName>

<DataField>Site</DataField>

</Field>

</Fields>

</DataSet>

</DataSets>

<Width>9.75in</Width>

<InteractiveHeight>11in</InteractiveHeight>

<Language>en-US</Language>

<TopMargin>1in</TopMargin>

</Report>

 

 

Acum , rulind pagina, observam ca se poate exporta raportul in Excel si PDF – mai mult decit sufficient:

 

Data viitoare vom vedea acelasi raport in WindowsForms...

 

Linkuri utile:

http://www.gotreportviewer.com/ - in partea dreapta aveti exemple de aplicatii care fac diverse – genereaza automat fisierele rdlc, scot automat fisierele Excel si multe altele

SQL Server Reporting Services – pentru utilizarea avansata a rapoartelor.

.NET | programare | tutoriale
Sunday, April 22, 2007 7:16:57 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Friday, April 06, 2007


implementare de interfata

   11 public class MockInterfaceOnObject<IInterface>

   12         where IInterface:class

Am vrut sa integrez backgroundworker-ul cu incarcarea din o tabela a obiectelor  - pentru a afisa intr-un grid incarcarea (nu astept pina se incarca toate ...)
Prima oara am zis : ok, pare sa fie destul de usor - incarc obiectele in DoWork-ul lui si trimit evenimente la adaugarea fiecarui copil(rind) care sa le prind si ... gata
Wrong.... trebuia sa imi dau seama ca evenimentele provin din alt thread decit al formei - si in consecinta trebuie sa fac begininvoke


Ok, mi-am zis - atunci de ce sa nu invoc direct ReportProgress ca sa raportez progresul operatiei si sa ma folosesc direct de evenimentele backgroundworker-ului?
Bun-dar obiectele mele sunt intr-o clasa separata- care nu stie NIMIC despre windowsforms - si e bine sa fie asa...
Care sa fie solutia?
Logic- o interfata care sa contina metodele principale din control, de genul:

   22  public interface IReportProgress

   23     {

   24         void ReportProgress(int percentProgress, object State);      

   25         void CancelAsync();

   26     }



Am zis-super, tot ce am de facut este sa fac cast de la control la interfata, sa o pasez la obiectul de incarcare si gata!
Wrong... cast de la control la interfata - acolo a fost problema adevarata...

Desi control-ul are TOATE metodele interfetei, deci TEORETIC implementeaza interfata, totusi nu se poate face cast ... NASOL!

Asa ca am deschis un forum pe RONUA si , in acelasi timp, m-am apucat sa fac o clasa generica care sa rezolve problema cast-ului intre un obiect si o interfata care contine metodele obiectului.
Am ajuns la o clasa

   11 public class MockInterfaceOnObject<IInterface>

   12         where IInterface:class


cu 2 metode principale:


   18  public static T MockObject<T>()

   19             where T:class


care intoarce un obiect NOU care il mosteneste pe T(backgroundworker) si implementeaza interfata IInterface - se foloseste cind vreti sa creati un obiect nou

   

   25 public static IInterface MockInterface(object obj)



care construieste un obiect nou ce are un constructor ce primeste ca argument obiectul trimis si implementeaza interfata facind apel la functiile corespunzatoare obiectului trimis - se foloseste cind obiectul deja exista , are anumite proprietati setate si vreti sa il folositi.



Nu am putut folosi metoda 1 pentru a face new pe backgroundworker -nu ca nu ar fi compilat, dimpotriva... Dar design-time de la WindowsForms se incapatina sa dea eroare.

Asa ca am folosit 2, cu ceva de genul


   70 MockInterfaceOnObject<IReportProgress>.MockInterface(backgroundWorker1)

      

Si a mers OK
Pe RONUA somalezu a dat inca o solutie, cu Real Proxy care pare sa fie interesanta. O sa o studiez. Pina atunci , iata codul:


using System;

using System.Collections.Generic;

using System.Text;

using System.CodeDom.Compiler;

using System.Reflection;

using Microsoft.CSharp;

using System.IO;

 

namespace MockInterface

{

    public class MockInterfaceOnObject<IInterface>

        where IInterface:class

    {

        private static Type TypeInterface()

        {

            return typeof(IInterface);

        }

        public static T MockObject<T>()

            where T:class

        {

            return ObjectWithInterface(typeof(T), GenerateInheritance(typeof(T)), null) as T;           

        }

        public static T MockObject<T>(T obj)

           where T : class

        {

            return ObjectWithInterface(typeof(T), GenerateEncapsulation(typeof(T)), obj) as T;

        }

        public static IInterface MockInterface(Type t)

        {

 

 

            return ObjectWithInterface(t, GenerateInheritance(t), null) as IInterface;

 

 

        }

        public static IInterface MockInterface(object obj)

        {

            return ObjectWithInterface(obj.GetType(), GenerateEncapsulation(obj.GetType()), obj) as IInterface;

        }

 

 

        private static string CodeBase(string pathfile)

        {

            if (pathfile == null)

                return null;

 

            if (pathfile.IndexOf("file:///") == 0)

                pathfile = pathfile.Substring("file:///".Length);

 

            return pathfile;

        }

 

        private static string CodeBase(Assembly a)

        {           

            return CodeBase(a.CodeBase);

 

        }

        public static object ObjectWithInterface(object Existing)

        {

            return null;

        }

        public static object ObjectWithInterface(Type t,string Code,params object[] args)

        {

 

            CSharpCodeProvider cs = new CSharpCodeProvider();

            CompilerParameters cp = new CompilerParameters();

            cp.GenerateExecutable = false;

            cp.GenerateInMemory = true;

            cp.ReferencedAssemblies.AddRange(new string[] { CodeBase(t.Assembly), CodeBase(TypeInterface().Assembly) });

            foreach (AssemblyName a in t.Assembly.GetReferencedAssemblies())

            {

 

                string pathfile = CodeBase(a.CodeBase);

                if (pathfile != null && (!cp.ReferencedAssemblies.Contains(pathfile)))

                    cp.ReferencedAssemblies.Add(pathfile);

 

            }

 

 

            CompilerResults cr = cs.CompileAssemblyFromSource(cp, new string[1] { Code });

            if (cr.Errors.Count > 0)

            {

                CompilerError ce = cr.Errors[0];

                throw (new ArgumentException("Can not compile file : " + ce.ErrorText + " Line:" + ce.Line));

            }

            return Activator.CreateInstance(cr.CompiledAssembly.GetExportedTypes()[0],args);

        }

 

        private static string GenerateInheritance(Type t)

        {

 

            StringBuilder sb=new StringBuilder();

            sb.AppendLine("namespace " + t.Namespace);

            sb.AppendLine("{");

            sb.AppendLine("public class My" + t.Name + " : " + t.Name + "," + TypeInterface().FullName);

            sb.AppendLine("{");

            sb.AppendLine("}");

            sb.AppendLine("}");

            return sb.ToString();

        }

        private static string GenerateEncapsulation(Type t)

        {

 

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("namespace " + t.Namespace);

            sb.AppendLine("{");

            sb.AppendLine("public class My" + t.Name + " : "  + TypeInterface().FullName);

            sb.AppendLine("{");

            sb.AppendLine("private " + t.Name + " m_obj;");

            sb.AppendLine("public My" + t.Name + "(" + t.Name + " obj){");

            sb.AppendLine("m_obj = obj;");

            sb.AppendLine("}");

            foreach (MethodInfo mi in TypeInterface().GetMethods())

            {

                bool isvoid  = (mi.ReturnType== typeof(void));

                string returntype = mi.ReturnParameter.ParameterType.FullName;

                if (isvoid)

                    returntype = "void";

 

                sb.AppendLine("public " + returntype + " " + mi.Name + "(");

                sb.AppendLine(" ");

                string strParams = " ";

                foreach(ParameterInfo pi in mi.GetParameters())

                {

                    sb.Append(pi.ParameterType.FullName + " " + pi.Name  + ",");

                    strParams += pi.Name +",";

                }

 

                strParams = strParams.Substring(0, strParams.Length - 1);//remove ,

                sb.Length =sb.Length-1;//remove ,

 

                sb.AppendLine(")");

                sb.AppendLine("{");

                if (!isvoid)

                    sb.AppendLine("return ");

 

                sb.AppendLine(" m_obj." +  mi.Name + "(" + strParams + ");");

                sb.AppendLine("}");

            }

 

            sb.AppendLine("}");

            sb.AppendLine("}");

 

            return sb.ToString();

        }

 

 

    }

}




( si nu stiu cind o sa ma obisnuiesc sa il si comentez...)

.NET | programare
Friday, April 06, 2007 9:50:21 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  |  Trackback


Saturday, March 31, 2007


refactoring
Am terminat cartea de Refactoring de Martin Fowler
(multumesc de 2 ori, Somalezule!)

Ce mi-a placut cel mai mult:

Introduce Null Object
 
if (customer == null) plan = BillingPlan.basic();
else plan = customer.getPlan();
 
 
 
Ron Jeffries
We first started using the null object pattern when Rich Garzaniti found
that lots of code in the system would check objects for presence before
sending a message to the object. We might ask an object for its person,
then ask the result whether it was null. If the object was present, we
would ask it for its rate. We were doing this in several places, and the
resulting duplicate code was getting annoying.
So we implemented a missing-person object that answered a zero rate
(we call our null objects missing objects). Soon missing person knew a
lot of methods, such as rate. Now we have more than 80 null-object
classes
 

Separate Domain from Presentation
 
If you have a grid, create a class to represent the rows on the grid. Use a collection on
the domain class for the window to hold the row domain objects.
 
( asta cu griudul nu o faceam intotdeauna- se potriveste cu ce zicea Lhotka: ok to duplicate fields, not ok to duplicate behaviour)

.NET | carti | programare
Saturday, March 31, 2007 3:30:14 PM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  |  Trackback


Friday, March 30, 2007


for each, list si predicate
Am avut ieri de selectat dintr-o lista de carti (aflate intr-un fisier txt) cele care ma intereseaza - mai bine spus, de scos cele care nu ma intereseaza - si trimis lista inapoi .
La inceput, am inceput sa fac normal:

   30             string[] lines = File.ReadAllLines(@"C:\lista.txt");

   31             foreach (string line in lines)

   32             {

   33                 if (line.ToLower().IndexOf("java") > 0)

   34                     continue;

   35 

   36                 if (line.ToLower().IndexOf("autocad") > 0)

   37                     continue;

   38 

   39                 if (line.ToLower().IndexOf("cisco") > 0)

   40                     continue;

   41 

   42                 l.Add(line);

   43             }

   44             string strNewFile = @"C:\lista1.txt";

   45             if (File.Exists(strNewFile))

   46                 File.Delete(strNewFile);

   47 

   48             File.WriteAllLines(strNewFile, l.ToArray());

   49

   50             System.Diagnostics.Process.Start(strNewFile);




( de aici se vede clar ca am scos java, cisco , si altele ...)

Apoi - am inceput sa gindesc - si sa imi aduca aminte ca exista ceea ce se numeste Predicate

Asa ca am ajuns la urmatorul text :


   28         static Predicate<string> NotInStringFirstTry(string x)

   29         {

   30 

   31             return new Predicate<string>(

   32                     delegate(string line)

   33                     {

   34 

   35                         if (x == null && line == null)

   36                             return false;

   37                         if (x == null)

   38                             return true;

   39                         if (line == null)

   40                             return true;

   41                         return (line.ToLower().IndexOf(x.ToLower()) < 0);

   42                     }

   43                     );

   44         }

   45         static void Main(string[] args)

   46         {

   47             string[] lines = File.ReadAllLines(@"C:\lista.txt");

   48 

   49             List<string> l = new List<string>();

   50             l.AddRange(lines);

   51 

   52 

   53             l = l.FindAll(NotInStringFirstTry("java"));

   54             l = l.FindAll(NotInStringFirstTry("cisco"));

   55             l = l.FindAll(NotInString("autocad"));

   56 

   57             string strNewFile = @"C:\lista1.txt";

   58             if (File.Exists(strNewFile))

   59                 File.Delete(strNewFile);

   60 

   61             File.WriteAllLines(strNewFile, l.ToArray());

   62 

   63             System.Diagnostics.Process.Start(strNewFile);

   64         }



Nu numai ca e mai compact - e si mai simplu de inteles ...



Iar la a 3-a gindire mi-am dat seama ca fac prea multe iteratii in array - asa ca m-ar ajuta o singura functie:



   29 static Predicate<string> NotInString(params string[] x)

   30         {

   31 

   32             return new Predicate<string>(

   33                     delegate(string line)

   34                     {

   35 

   36                         if (x == null && line == null)

   37                             return false;

   38                         if (x == null)

   39                             return true;

   40                         if (x.Length == 0)

   41                             return true;

   42                         if (line == null)

   43                             return true;

   44                         foreach (string word in x)

   45                         {

   46                             bool b = (line.ToLower().IndexOf(word.ToLower()) > -1);

   47                             if (b)

   48                                 return false;

   49                         }

   50 

   51                         return true;

   52                     }

   53                     );

   54         }

   55 

   56         static void Main(string[] args)

   57         {

   58             string[] lines = File.ReadAllLines(@"C:\lista.txt");

   59 

   60             List<string> l = new List<string>();

   61             l.AddRange(lines);

   62             l = l.FindAll(NotInString("java", "cisco", "autocad"));

   63 

   64             string strNewFile = @"C:\lista1.txt";

   65             if (File.Exists(strNewFile))

   66                 File.Delete(strNewFile);

   67

   68             File.WriteAllLines(strNewFile, l.ToArray());

   69

   70             System.Diagnostics.Process.Start(strNewFile);

   71         }




Plina de peripetii, programarea asta ... Daca aveti o alta sugestie, astept sa imi spuneti
( codul a fost copiat cu ajutorul CSAH)
http://www.jtleigh.com/people/colin/software/CopySourceAsHtml/





.NET | programare
Friday, March 30, 2007 8:40:21 AM (GMT Daylight Time, UTC+01:00)  #    Comments [7]  |  Trackback


Saturday, March 24, 2007


Programarea in .NET - partea a 14-a Salvare XML si Executare de operatii asincrone in Windows Forms

De ce taskuri asincrone ? In ideea ca , intr-o aplicatie Windows(si chiar ASP.NET) , operatiile lungi ar trebui sa fie executate de catre alt thread, urmind ca aplicatia sa poata sa mai afiseze ceva utilizatorulu in tot acest timp ( fie si un buton pe care scrie „apasa ca sa intrerupi operatia asta lunga ...”). De pilda, in aplicatia noastra, daca avem mai mult de 100 de Publisher-i si vrem sa ii vedem pe toti – ar trebui incarcati intr-un nou thread.

 

Ne ocupam mai intii de o aplicatie Windows Forms si pe urma de ASP.NET

Un thread nu e greu de pornit. Hai sa vedem un exemplu:

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(StartAction));

            t.Start("obiect transmis");

 

 

public void StartAction(object o)

        {

            string s = o.ToString();

            System.Threading.Thread.Sleep(5000);

            //executa actiunea

            //trimite text

            if (this.InvokeRequired)

            {

                this.Invoke((MethodInvoker)delegate()

                 {

                     this.Text = s;

                 });

                //sau

                //this.Invoke(new MethodInvoker(evenimentfaraparametri());

                //this.Invoke(new EventHandler(btnDiscounts_Click));

                //this.BeginInvoke(new EventHandler(eveniment cu parametri));

            }

            else

                this.Text = s;

        }

 

 

Totusi, exista o problema – dintr-un thread nu se pot accesa DIRECT controale din alt thread – si de aceea avem instructiunea this. Invoke .Diferenta intre this.Invoke si este this.BeginInvoke aceea ca prima instructiune asteapta rezultatul actiunii, pe cind a doua doar executa si se intoarce imediat sa execute codul ramas.

 

De aceea exista controlul numit BackgroundWorker – care asigura ca , din evenimentul propriu generat, sa accesezi orice obiect de pe forma. O sa facem acest lucru pentru salvarea in XML a colectiei de Publisher-i in format XML.

.NET are o forma usoara de a salva o colectie/clasa in format XML , salvindu-i proprietatile.

Vom utiliza modalitatea cea  mai usoara de a face acest lucru

Marcam clasa Publisher si clasa colectie ColPublisher cu atributul de   [Serializable] :

 

[Serializable]

    public class ColPublisher : System.Collections.ObjectModel.KeyedCollection<string,Publisher>

 

[Serializable]

    public class Publisher

 

Acum o sa facem serializarea obiectului Publisher:

#region Serializer

        /// <summary>

        /// instanta pentru lazy load

        /// </summary>

        private static XmlSerializer m_Serializer;

        /// <summary>

        /// serializator pentru obiectul publisher

        /// </summary>

        private static XmlSerializer Serializer

        {

            get

            {

                if (m_Serializer == null)

                    m_Serializer = new XmlSerializer(typeof(Publisher));

 

                return m_Serializer;

            }

        }

 

        /// <summary>

        /// salveaza obiectul ca XML

        /// </summary>

        [XmlIgnore]

        public string XML

        {

            get

            {

                StringBuilder sb = new StringBuilder();

                EncodingStringWriter sw = new EncodingStringWriter(sb, Encoding.Default);

                XmlTextWriter xtw = new XmlTextWriter(sw);

                Serializer.Serialize(xtw, this);

                return sb.ToString();

 

 

            }

        }

        /// <summary>

        /// recreeeaza un Publisher dintr-un string XML

        /// </summary>

        /// <param name="XML">string care contine tot </param>

        /// <returns></returns>

        public static Publisher FromXML(string XML)

        {

            StringReader sr = new StringReader(XML);

            return Serializer.Deserialize(sr) as Publisher;

        }

        #endregion

 

 

   

Copiem apoi acelasi cod( cu citeva diferente) si pentru ColPublisher

 

Citeva comentarii despre cod:

De ce am pus [XmlIgnore] peste  public string XML ? Pentru a nu serializa si aceasta proprietate, dind astfel nastere la o nedorita recursivitate

Ce e cu clasa EncodingStringWriter ? Este facuta pentru a putea schimba Encoding=ul- daca aveti de exemplu caractere speciale(diacritice) romanesti/franceze/etc.

De ce metoda FromXML este statica- iar XML este pe instanta? Asa mi se pare normal – transformarea dintr-un obiect in XML sa apartina obiectului, iar din XML in obiect nu poate sa apartina unui obiect( ah, daca as fi putut scrie this = Serializer.Deserialize(sr) as Publisher  !) - ci doar clasei.

Nu se poate face codul mai „generic”? Ba da- una din deosebiri ar fi ca FromXML ar trebui sa fie pe instanta...

 

 

Haideti acum in proiectul Windows sa serializam o colectie de Publisher-i.Pe forma frmPublisherList adaugam un buton btnSave, cu textul Save, dublu click si scriem urmatorul cod:

private void btnSave_Click(object sender, EventArgs e)

        {

            BookObjects.ColPublisher col = colPublisherBindingSource.DataSource as BookObjects.ColPublisher;

            string strSave = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);

            strSave = Path.Combine(strSave, "pub.xml");

            File.WriteAllText(strSave, col.XML);

            System.Diagnostics.Process.Start(strSave);

        }

 

 

Rulati proiectul, adaugati 2 publisher-i si apasati pe save.

Este clar ca, daca sunt multi publisher-i, procesul poate deveni prea lung si blocheaza interfata.

 

Haideti sa folosim background worker. Il adaugam din toolbox , il redenumim bgSave, dublu click. Luam codul din btnSave_Click, il adaugam la si pe urma scriem doar bgSave.RunWorkerAsync();

 

private void btnSave_Click(object sender, EventArgs e)

        {

            bgSave.RunWorkerAsync();

        }

 

        private void bgSave_DoWork(object sender, DoWorkEventArgs e)

        {

            BookObjects.ColPublisher col = colPublisherBindingSource.DataSource as BookObjects.ColPublisher;

            string strSave = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);

            strSave = Path.Combine(strSave, "pub.xml");

            File.WriteAllText(strSave, col.XML);

            System.Diagnostics.Process.Start(strSave);

 

        }

 

Data viitoare  o sa vorbim despre modelul asincron din ASP.NET.

.NET | programare | tutoriale
Saturday, March 24, 2007 1:59:38 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Wednesday, March 21, 2007


iarasi teste free pe Brainbench
La pagina
http://www.brainbench.com/xml/bb/common/testcenter/freetests.xml#sponsored
 
Sunt teste de
MS Windows Server 2003 Administration
Network Security
RDBMS Concepts

 
Pentru cei pasionati, aveti si English Vocabulary,Personality Assessment, si altele.
Perioada limitata....

.NET | programare
Wednesday, March 21, 2007 3:54:40 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, March 20, 2007


Avantajele Dataset/DataTable

Am descoperit, cu uimire, virtutile Dataset si DataTable. Sunt extraordinare pentru proiecte one-shot!

Am avut de facut o integrare intre SQL SERVER, MySQL si ORACLE(date care trebuiau verificate, mapate, schimbate, vazut diferente, grupate, etc)

Dataset-ul s-a dovedit a fi unealta perfecta pentru join-uri intre tabele, pentru filtrari si altele.

Admiratia mea pentru OO a mai scazut un pic – pentru ca – chiar si cu CodeSmith – tot era destul de greu de scris asa ceva.

 

.NET | programare
Tuesday, March 20, 2007 8:52:37 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Saturday, March 17, 2007


Tutorial .NET - p13 - Log-area operaţiilor cu log4net

In orice aplicaţie este bine sa ţinem evidenta operaţiilor făcute de utilizator( ce a modificat sau chiar ce a văzut). In acest scop putem folosi fie mecanismul de trace din .net,  fie o soluţie proprie, fie Logging and Instrumentation Application Block(http://msdn2.microsoft.com/en-us/library/ms998162.aspx), fie log4net(http://logging.apache.org/log4net/

 

Vom utiliza in acest exemplu log4net .El suporta log-area operaţiilor in felurite moduri – in fişier, baza de date, email, telnet si multe altele.

Downloadati versiunea 1.2.10 de la adresa http://logging.apache.org/log4net/downloads.html si sa începem configurarea aplicaţiei. Copiaţi conţinutul folder-ului log4net-1.2.10\bin\net\2.0\debug in C:\Book\sharedDll si sa începem modificarea proiectului Windows pentru a înregistra ce a făcut utilizatorul

 

Deschidem Book.sln si deschidem App.Config. Acolo scriem următoarele imediat sub configuration:

  <configSections>

    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

  </configSections>

  <log4net>

    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">

      <File value="Log4Net.log"/>

      <AppendToFile value="true"/>

      <rollingStyle value="Composite"/>

      <maximumFileSize value="1MB"/>

      <maxSizeRollBackups value="10"/>

      <datePattern value="yyyyMMdd"/>

      <layout type="log4net.Layout.PatternLayout">

        <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>

      </layout>

    </appender>

    <root>

      <level value="Debug"/>

      <appender-ref ref="RollingLogFileAppender"/>

    </root>

  </log4net>

 

 

După cum se vede, folosim RollingLogFileAppender ( adică un fişier a cărui denumire va fi diferita in fiecare zi după modelul datePattern ) de tipul Composite(daca depaseste  maximumFileSize atunci se creează un nou fişier in ziua respectiva).

 

Sa adăugam referinţa proiectului nostru (BookWin) dll-ul log4net.dll din sharedDll .Avem de făcut următoarele in Program.cs :

In funcţia Main scriem prima linie:

log4net.Config.XmlConfigurator.Configure();

apoi adăugam următorul membru in clasa Program:

public static readonly log4net.ILog logger = log4net.LogManager.GetLogger("RollingLogFileAppender");

 

Haide sa scriem in fişier de cite ori un utilizator adaugă un nou Publisher.

In frmPublisherAdd.cs, la evenimentul private void btnAdd_Click(object sender, EventArgs e) vom adăuga codul de log-are:

if (Program.logger.IsDebugEnabled)

                Program.logger.Debug("Adaugat publisher cu numele:" + p.Name);

 

Cam atit e de făcut. Acum rulaţi proiectul, adaugaţi un Publisher, si o sa vedeţi un fişier log4Net.log in care scrie următoarele:

 

<data> [1] DEBUG RollingLogFileAppender Adaugat publisher cu numele:newpub

 

 

E interesant la log4Net ca puteţi adăuga mai mulţi appender-i, astfel ca , de pilda, sa trimită si email de cate ori o modificare e făcuta.

 Observatie 1:

Pentru aplicatia Web, modificarile in Web.Config sunt aceleasi - iar in global.asax trebuie pusa linia urmatoare:

 void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup      
        log4net.Config.XmlConfigurator.Configure();   
    }

Observatie 2:

In loc sa punem codul in fiecare pagina de Web si Windowspe salvare, mai bine punem in fiecare cod de "salvare" al obiectelor- de pilda in public void Save()

Lectura obligatorie: documentaţia de log4net...

 

.NET | programare | tutoriale
Saturday, March 17, 2007 2:15:50 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, March 11, 2007


Tutorial .NET : generarea documentatiei proiectului

Documentarea - Scrierea de fişiere Help.

 

In .NET sunt doua tipuri mari de fişiere Help : Cele care produc Help pentru utilizatorul final si cele care sunt auto-generate din comentarii la cod.

 

Avem nevoie de următoarele:

1.Html Help Workshop – e free si puteţi sa îl downloadati de aici

http://www.microsoft.com/downloads/details.aspx?familyid=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en. Adiţional puteţi downloada si fişiere css stil Office de aici

http://www.microsoft.com/downloads/details.aspx?FamilyId=A6A76073-0E0A-49BB-8E21-318B798B4CF6&displaylang=en

 

 

2. Pentru documentaţia codului exista înainte NDoc – dar din păcate dezvoltatorul nu mai face dezvoltarea pentru .Net 2.0( vezi http://johnsbraindump.blogspot.com/2006/07/ndoc-20-is-dead.html)

Alternativa este SandCastle (http://www.sandcastledocs.com) din care ultimul CTP este aici (http://www.microsoft.com/downloads/details.aspx?FamilyID=E82EA71D-DA89-42EE-A715-696E3A4873B2&displaylang=en).

 

3.De asemenea, pentru ca SandCastle e greu de utilizat din command line, exista mai multe GUI-uri pentru el – intre care vom lucra cu SandCastle Help File Builder de pe CodePlex (http://www.codeplex.com/Wiki/View.aspx?ProjectName=SHFB). O sa lucram cu ultimul release ,1.3.3.1 PROD aflat aici

http://www.codeplex.com/SHFB/Release/ProjectReleases.aspx?ReleaseId=1209

si as downloada chiar sursele ...

 

Începem cu documentarea codului pentru BookObjects, urmând sa trecem la generarea de Help pentru proiectul Windows.

 

Comentariile in C# se fac scriind trei slash-uri deasupra clasei/metodei/cimpului pe care vreţi sa le documentaţi:

/// <summary>

/// Aceasta clasa tine toti publisher-ii

/// Mod de utilizare : folositi Load

/// </summary>

public class ColPublisher : System.Collections.ObjectModel.KeyedCollection<string,Publisher>

{

 

/// <summary>

/// varianta interna de generat cheie unica pentru un Publisher

/// </summary>

/// <param name="item">publisher-ul</param>

/// <returns></returns>

protected override string GetKeyForItem(Publisher item)

{

Continuaţi cu toate metodele sau downloadati ultima varianta de proiect de aici:

http://serviciipeweb.ro/iafblog/content/binary/part12/book.zip

 

In plus, trebuie sa mai setaţi faptul ca trebuie generata documentaţia XML din proprietatile proiectului:

 

 

Acum in folder-ul C:\Book\BookObjects\bin\Debug aveţi generata documentaţia XML. Pornim SandCastle Help File Builder care arata cam asa:

 

 

Apăsam pe Add si ne ducem in C:\Book\BookObjects\bin\Debug. Acolo indicam dll-ul generat iar programul o sa „observe” si fişierul XML. Apăsam pe iconiţa de compilare si ... eroare...

Error: Unresolved assembly reference: System.Configuration (System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) required by BookObjects

Last step completed in 00:00:02.403

 

 

După descriere vedem că ii lipseşte o referinţa la System.Configuration. Acest dll se afla in GAC (Global Assembly Cache) si o vom adăuga. In Project Properties , la Build=>Dependencies apăsaţi pe butonul cu cele 3 puncte.

Acum in ecranul următor exista un buton cu imaginea de folder si cu o icoana de o cheie care iese, iar la tooltip scrie „Add GAC dependencies”

 

 

Apăsaţi pe el si căutaţi System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a in lista care urmează.

 

Acum spune ca ii lipseşte un XSL(Error: The transform file 'C:\Program Files\Sandcastle\ProductionTransforms\AddOverloads.xsl' could not be loaded. The error is: Could not find file 'C:\Program Files\Sandcastle\ProductionTransforms\AddOverloads.xsl'.). Pentru asta fie downloadati un CTP de SandCastle mai vechi sau Visual Studio 2005 SDK Version 4.0 de la adresa http://www.microsoft.com/downloads/details.aspx?FamilyID=51a5c65b-c020-4e08-8ac0-3eb9c06996f4&DisplayLang=en si copiaţi XSL-ul cu pricina in folder-ul <Program Files>\ Sandcastle\ProductionTransforms, alături de celelalte.

 

Acum rulati din nou si ceea ce se va genera este un document chm , numit Documentation.chm aflat in C:\Book\BookObjects\bin\Debug\Help:

 

 

Putem personaliza ceea ce se generează destul de uşor, modificând setările de aici:

 

 

E clar acum ca aceasta documentaţie se poate regenera la cerere.

 

Sa generam acum documentaţia pentru Windows Forms.

Ar trebui pentru fiecare forma sa avem cate un Help – aşa ca o sa cream 3 fişiere HTML care o sa tina List, Add si Update.

 

Vom crea un nou folder, numit HelpWindows, in C:\book\Help si vom pune in el cele 3 fişiere : add.htm,list.htm,update.htm.

Pornim HTML Help Workshop, File=>New =>Project si daţi next. Adaugati fişierele htm si apăsati pe Contents. Acceptaţi creerea unui nou fişier si apăsând pe iconiţa din stânga cu aspect de fişier adăugat la conţinut cele 3 fisiere, dindu-le numele corespunzătoare. Acum, după compilare, s-a generat un fişier chm. Haideţi sa îl integram cu aplicaţia Windows.

 

 

Sarcina de a copia fişierul chm lângă executabil o las cititorului, având in vedere ca am mai făcut aşa ceva(Project=>Properties=>Build Events). Sa mergem la forma de list si sa adaugam din ToolBox un control HelpProvider. LA proprietati la HelpNameSpace puneti numele chm-ului. Acum pe forma, gasiti HelpKeyword on... (setati valoarea la list.htm) si HelpNavigator on...( setat la topic). Rulati, apasati F1 si iata fisierul de help!

 

Puteti downloada ultimele surse de aici

http://serviciipeweb.ro/iafblog/content/binary/part12/book.zip

 

Lecturi utile:

GAC http://www.codeproject.com/dotnet/DemystifyGAC.asp

MSHelp 2.0 http://www.helpware.net/mshelp2/h20.htm

 

 

 

 

 

 

 

.NET | programare | tutoriale
Sunday, March 11, 2007 6:29:11 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, March 04, 2007


Teste automate cu NUnit- partea 11
De ce ar trebui sa faceti teste automate ?

Din mai multe motive :

1.      Pentru ca e o modalitate usoara de a releva functionalitatile mari ale aplicatiei

2.      Pentru ca la orice modificare la care nu sunteti sigur daca dauneaza cumva logicii aplicatiei puteti rula testele vechi si vedeti daca ati stricat ceva sau nu(Nota : ar trebui sa adaugati un nou test pentru cei care vin dupa voi )

3.      E mai usor de fixat bug-urile daca, pe deasupra, rulati testele in fiecare noapte – si a doua zi dimineata vedeti ceva stricat...

4.       

Hai sa trecem la treaba:

 

Mai intii downloadati NUnit de la http://www.nunit.org/index.php?p=download ( eu am folosit versiunea 2.2.8 )Exista si surse si setup de instalare. Eu as sfatui sa luati sursele sa le compilati.

Apoi la solutia noastra Book.sln adaugam un nou proiect de tipul Class Library , numit BookTest , adaugam o referinta la nunit.framework.dll , aflat in NUnit-2.2.8-src\src\NUnitFramework\framework\bin\Debug2005, modificam class1.cs in TestPublisher.cs si incepem sa scriem testul.Testul cel mai simplu este unul de CRUD – create , read, update, delete.

Avem nevoie de obiectele Publisher respective, precum si de setari in fisierul App.Config pentru a recunoaste Baza de date, precum si de Baza de date.

Pentru Publisher, adaugam o referinta la BookObject in tab-ul „Projects” de la Add Reference.

Pentru App.Config, adaugam un fisier de tipul application configuration file si copiem de la BookDos partile relevante, astfel incit fisierul arata astfel :

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<appSettings>

<add key="DatabaseUsed" value="MDB"/>

<!-- possible values : MDB, SQLServer-->

</appSettings>

<connectionStrings>

<add name="MDB" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\book.mdb;User Id=admin;Password=;"/>

<!-- TODO : add for asp.net application the connection string with SQL Server-->

</connectionStrings>

</configuration>

 

Pentru baza de date, e simplu : in Build Events, la Post Build Command Line adaugam

copy $(ProjectDir)..\BookData\*.mdb $(TargetDir)

Acum putem incepe sa scriem testul :

 

 

using System;

using System.Collections.Generic;

using System.Text;

using NUnit.Framework;

using BookObjects;

namespace BookTest

{

[TestFixture] //arata ca e o clasa care contine teste

public class TestPublisher

{

[Test] //arata ca metoda care urmeaza este un test

[Category("CRUD")] //categoria -de obicei, testele de CRUD ar trebui puse impreuna

public void CRUD()

{

Publisher p = new Publisher();

p.Name = "Amazon";

p.Save();

 

//sa il gasim

ColPublisher cp = new ColPublisher();

cp.Load();

bool bFound= false;

foreach (Publisher pLoop in cp)

{

if (pLoop.Name == p.Name)

{

bFound = true;

break;

}

}

//daca acea conditie(bFound) nu e true, atunci se afiseaza mesajul de eroare

Assert.IsTrue(bFound, "Nu s-a gasit publisher cu numele " + p.Name + " dupa insert");

//sa il modificam

p.Name = "O'Reilly";

p.Update();

 

//sa il gasim din nou

cp = new ColPublisher();

cp.Load();

bFound = false;

foreach (Publisher pLoop in cp)

{

if (pLoop.Name == p.Name)

{

bFound = true;

break;

}

}

//daca acea conditie(bFound) nu e true, atunci se afiseaza mesajul de eroare

Assert.IsTrue(bFound, "Nu s-a gasit publisher cu numele " + p.Name + " dupa update");

 

//acum sa il stergem

p.Delete();

 

//si sa vedem ca nu a fost gasit

cp = new ColPublisher();

cp.Load();

bFound = false;

foreach (Publisher pLoop in cp)

{

if (pLoop.Name == p.Name)

{

bFound = true;

break;

}

}

 

//daca acea conditie(bFound) nu e false, atunci se afiseaza mesajul de eroare

Assert.IsFalse(bFound, "S-a gasit publisher cu numele " + p.Name + " dupa delete");

 

 

 

}

}

}

 

 

Il compilam si sa rulam testul. Gasiti in folderul NUnit-2.2.8-src\src\GuiRunner\nunit-gui-exe\bin\Debug2005 un nunit-gui.exe si porniti-l.Apasati File=> Open si mergeti in C:\Book\BookTest\bin\Debug si incarcati BookTest.dll . Ar trebui sa apara figura urmatoare

 

Apasati pe RUN si primul lucru pe care il vedeti este:

 

 

Se vede clar ca e ceva prost... ne uitam in TestPublisher.cs si vedem ca la linia 37 este

p.Update();

Ceva a mers prost la update ... sa vedem linia 107 din Publisher.cs

strSQL += "'" + this.Site.Replace("'", "''") + "'";

Acum e clar ce s-a intimplat ... Cind am facut testul, nu am initializat Site-ul cu nimic... si atunci este null , ceea ce inseamna ca .Replace nu poate fi aplicat

Sa modificam codul din Publisher.cs ca sa ia in seama si acest lucru :

if (this.Site == null)

strSQL += " NULL ";

else

strSQL += "'" + this.Site.Replace("'", "''") + "'";

 

Acum apare alta eroare :

 

Este destul de clar ca aplicatia nu a updatat numele ...

De ce ?Ne dam seama imediat : in momentul in care aplicatia a adaugat un nou Publisher , nu a regasit ID-ul inserat ... iar cind a facut update, IDPublisher este 0 , ceea ce inseamna ca nu a putut fi facut update corect.

Cum modificam acest lucru ? Pentru access , putem sa selectam maxim de ID,iar pentru SQL Server putem crea o procedura stocata ... sau sa intoarcem @@Identity

Hai sa facem pentru Access , modificand Publisher.cs, procedura Save, adaugind la final:

if(Settings.TheDatabase == Settings.DatabaseUsed.MDB)

{

 

strSQL = "select max(IDPublisher) as nr from Publisher";

using (DbConnection dc = Settings.TheConnection)

{

dc.Open();

using(DbCommand dco =Settings.TheCommand)

{

dco.CommandType = System.Data.CommandType.Text;

dco.CommandText = strSQL;

dco.Connection = dc;

object o = dco.ExecuteScalar();

this.IDPublisher = int.Parse(o.ToString());

}

}

}

Acum rulam din nou testul si totul e verde , ceea ce e de bine :

 

 

E clar ca exemplu a fost mai degraba simplut, iar ceea ce conteaza, de fapt, sunt regulile de business si de validare - ca de exemplu, validarea CNP

 

 

.NET | programare | tutoriale
Sunday, March 04, 2007 12:20:30 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, February 27, 2007


Prezentare RONUA
Am facut prezentarea la RONUA, impreuna cu Andrei Maxim , Hilde Corbu si Aurelian Popa

Super interesanta prezentarea lui Andrei. Pe a lui Hilde nu am reusit sa o urmaresc(telefoane, vorbit cu mai mult cu Bogdan Ciungu cu care nu ma vazusem de mult si pe care il simpatizez mult), iar a lui Aurelian nu am vazut-o din cauza ca la servici avusesem ceva urgent de facut- si trebuia terminat

Acum propun sa cititi 2 rinduri de prezentari:
Cea propusa de MS : link
Cea facuta de mine : link

Ce e mai important sunt linkurile:

Linkuri documentatie :

Excel 2002 si XML
http://support.microsoft.com/kb/288215
 Office 2003: XML Reference Schemas
http://www.microsoft.com/downloads/details.aspx?familyid=fe118952-3547-420a-a412-00a2662442d9&displaylang=en
ECMA-376 -Office Open XML File Formats
http://www.ecma-international.org/publications/standards/Ecma-376.htm

Linkuri utile:
Free Excel Xml Writer Library
http://www.carlosag.net/Tools/ExcelXmlWriter/Default.aspx
Open XML Translator enables interoperability with ODF
http://openxmldeveloper.org/archive/2007/02/02/1172.aspx
Open XML Package Explorer
http://www.codeplex.com/PackageExplorer

.NET | Excel | programare | tutoriale
Tuesday, February 27, 2007 8:46:09 PM (GMT Standard Time, UTC+00:00)  #    Comments [3]  |  Trackback


Sunday, February 25, 2007


Tutorial .NET : Dos Project - very short demo

Open the book.sln solution and add a new project of type ConsoleApplication (name it  BookDos)

Add reference to the BookObjects project and add an app.config file and write to this file the same as in the corresponding app.config file from BookWin application.

The post build event on project – properties must be the same as for the BookWin

copy $(ProjectDir)..\BookData\*.mdb $(TargetDir)

 

In Program.cs file please enter the following code:

using System;

using System.Collections.Generic;

using System.Text;

using BookObjects;

 

namespace BookDos

{

    class Program

    {

        static void Main(string[] args)

        {

            ColPublisher col = new ColPublisher();

            col.Load();

            Console.WriteLine("Records Number:" + col.Count);

            foreach (Publisher p in col)

            {

                Console.WriteLine(p.Name);

            }

        }

    }

}

 

 

And, of course, the number of records will be 0 – as we do not have any records.


In the following we will show how to perform some automated tests with NUnit .

 

 

.NET | programare | tutoriale
Sunday, February 25, 2007 11:25:02 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, February 11, 2007


Programming in .NET - part 9 -site map and localization

The site map is relatively easy:

Add a new item – find “Site Map” and accept the default name (Web.sitemap)

And put the following

<?xml version="1.0" encoding="utf-8" ?>

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

  <siteMapNode url="default.aspx" title="Main"  description="First Page">

    <siteMapNode url="frmPublisherList.aspx" title="All publishers"  description="Publishers list" >

      <siteMapNode url="frmPublisher_Insert.aspx" title="New Publisher" description="Add new"></siteMapNode>

      <siteMapNode url="frmPublisher_Edit.aspx" title="Edit Publisher" description="Edit"></siteMapNode>

      <siteMapNode url="frmPublisher_Delete.aspx" title="Delete Publisher" description="Delete"></siteMapNode>

    </siteMapNode>

    <siteMapNode url="frmBookList.aspx" title="All books"  description="Book list" >

 

    </siteMapNode>

  </siteMapNode>

</siteMap>

 

( the names are pretty suggestive – url, title and description)

Now it’s time to put to work :

Open Book.master , and put a site map control ( find into the navigation tab on toolbox) before content place holder:

<asp:SiteMapPath ID="SiteMapPath1" runat="server" Font-Names="Verdana" Font-Size="0.8em" PathSeparator=" : ">

                            <PathSeparatorStyle Font-Bold="True" ForeColor="#990000" />

                            <CurrentNodeStyle ForeColor="#333333" />

                            <NodeStyle Font-Bold="True" ForeColor="#990000" />

                            <RootNodeStyle Font-Bold="True" ForeColor="#FF8000" />

                        </asp:SiteMapPath>

 

 

And put a tree view instead of right menu:

<asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1" MaxDataBindDepth="1">

                        </asp:TreeView>

                        <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />

 

 

 

Now, if you run the project, and press new  button, you will see the following

 

 

Sure that all books it is not implemented yet – but it is your task to do it.

 

Now we will proceed to the localization part. We want to be able that people see the content in English and French.

We will localize just one form, and we left the others as an exercise to the reader.

The setting of language will be set in a cookie on the user’s PC and will be read each time.

Add a drop down list to the master page, near Book application with the following code:

<asp:DropDownList runat="server" id="ddlLanguage" OnSelectedIndexChanged="ddlLanguage_SelectedIndexChanged" AutoPostBack="true">

                            <asp:ListItem Text="English" Value="en">

                            </asp:ListItem>

                            <asp:ListItem Text="French" Value="fr">

                            </asp:ListItem>

                        </asp:DropDownList>

 

 

On the .cs page, let’s store the actual configuration :

protected void ddlLanguage_SelectedIndexChanged(object sender, EventArgs e)

    {

        HttpCookie cookie = Request.Cookies["Language"];

        cookie.Value = ddlLanguage.SelectedValue;

        Response.AppendCookie(cookie);

        cookie.Expires = System.DateTime.Now.AddYears(1);

        Response.Redirect(Request.Url.LocalPath);

    }

 

 

 

So we have saved the value ... now, let’s retrieve it:

protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

            ChangeLanguage();

 

    }

    private void ChangeLanguage()

    {

        HttpCookie cookie = Request.Cookies["Language"];

        if (cookie == null)

        {

            //set default the cookie in web.config

            string s = Thread.CurrentThread.CurrentUICulture.Name;

            cookie = new HttpCookie("Language");

            cookie.Value = s;

            cookie.Expires = System.DateTime.Now.AddYears(1);

            Response.AppendCookie(cookie);

        }

 

 

        foreach (ListItem li in ddlLanguage.Items)

        {

            if (li.Value == cookie.Value)

            {

li.Selected = true;

                 break;           

}

 

        }

 

    }

 

 

 

Now we must change the language : We can put this on each page, overriding InitializeCulture , or put in a global.asax file( that retains the application events) on Application_BeginRequest: ( new item => Global Application Class)

 

    protected void Application_BeginRequest(object sender, EventArgs e)

    {

        string lang = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;

        HttpCookie cookie = Request.Cookies["Language"];

 

        if (cookie != null && cookie.Value != null)

            lang = cookie.Value;

 

        System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(lang);

        System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(lang);

    }

 

 

It is time now to proceed to the localization

Add an Asp.NET folder, named “App_LocalResources”

 

And in this folder, add three resource files, named :

frmPublisherList.aspx.en.resx

frmPublisherList.aspx.fr.resx

frmPublisherList.aspx.resx

(The file name is compose by the name of the aspx file + (optional) language + .resx )

In these files we will add just one string for the Text property of the button that is new, like in the figure:

 

 

Now, we put meta:resourcekey="btnNew" on the button:

<asp:Button ID="btnNew" runat="server" Text="New" OnClick="btnNew_Click" meta:resourcekey="btnNew"/>   

 

And we will see in this mode the translation by changing from English to French in the combo.

Attention: if you do not have the invariant culture file ( the one without language in the name) it does not work!

If you have several items that are invariant ( like the “save”  button) you can add resources to the special folder App_GlobalResources and add there resx files ( that now can be named as you want to ) As example suppose we have now in the App_GlobalResources the files

Buttons.en.resx

Buttons.fr.resx

Buttons.resx

And one resource named

btnSaveText

We can acces as so :

 

<%$ Resources:Buttons,btnSaveText%>

 

 

<asp:Button ID="btnSave" Text="<%$ Resources:Buttons,btnSaveText%>" runat="server" OnClick="btnSave_Click" />

Or , programatically, by writing :

Resources.Buttons.btnSaveText

 

Next time we will look at making a DOS project for the same application

Items to read:

Localization: http://quickstarts.asp.net/QuickStartv20/aspnet/doc/localization/localization.aspx

Master Pages:

http://quickstarts.asp.net/QuickStartv20/aspnet/doc/masterpages/default.aspx

.NET | ASP.NET | programare | tutoriale
Sunday, February 11, 2007 9:41:24 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Tuesday, February 06, 2007


add-in foarte bun la generatoare de cod
se cheama Smart Paster 1.1 Add-In
Are versiune de 1.1, are versiune de 2.0 si vine si cu cod sursa

Adresa:
http://weblogs.asp.net/alex_papadimoulis/archive/2004/05/25/Smart-Paster-1.1-Add-In---StringBuilder-and-Better-C_2300_-Handling.aspx

Mi-a folosit de minune!

.NET | programare | addin
Tuesday, February 06, 2007 9:18:03 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, February 04, 2007


tutorial .NET - p8 - edit in ASP.NET
 

Now we will edit the Publisher objects .

Add a new WebForm , name it frmPublisher_Insert.aspx and make sure the “Place code in separate file” and “Select master page” are both selected by default.

Change in source view the title from “Untitled Page” to “Insert Publisher”

Now we must put controls in place to insert publishers

There must be the name and site of the publisher.

I prefer enter a table for this and the page will look like this:

 

<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisher_Insert.aspx.cs" Inherits="frmPublisher_Insert" Title="Insert Publisher" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

    <table>

        <tr>

            <td colspan="2">Enter values

            </td>

        </tr>

        <tr>

            <td>

               Name

            </td>

            <td>

                <asp:TextBox ID="txtName" runat="server">

                </asp:TextBox>

            </td>

        </tr>

        <tr>

            <td>

               Site

            </td>

            <td>

                <asp:TextBox ID="txtSite" runat="server">

                </asp:TextBox>

            </td>

        </tr>

        <tr>

            <td><asp:Button ID="btnSave" Text="Insert" runat="server" />

            </td>

            <td><asp:Button ID="btnCancel" Text="Cancel" runat="server" />

            </td>

        </tr>

    </table>

</asp:Content>

 

Now switch to design view and double click on Insert button in order to generate Click event. Double click in solution explorer the frmPublisher_Insert.aspx and , in Design view, double click on Cancel button in order to generate Click event.

For cancel it is clear what we must do – redirect to the frmPublisherList.aspx

Response.Redirect("frmPublisherList.aspx", false);

For save button, we must create a new publisher and save

  Publisher p = new Publisher();

        p.Name = txtName.Text;

        p.Site = txtSite.Text;

        p.Insert();

        Response.Redirect("frmPublisherList.aspx", false);

Please try it by setting the frmPublisher_Insert.aspx as start page and run the project (F5)

If all works well (please ensure that Insert has a call to Save()) you will see in the frmPublisherList.aspx the item you just selected.

It is clear that frmPublisherList.aspx has a need for a new button . Let’s put it

<asp:Button ID="btnNew" runat="server" Text="New" OnClick="btnNew_Click" />

And on code:

protected void btnNew_Click(object sender, EventArgs e)

    {

        Response.Redirect("frmPublisher_Insert.aspx", false);

    }

That will be ok for adding a new publisher.

Now for editing and deleting we can make on list… but I prefer having 2 new pages.

So modify a little bit the code on the grid, in order to have the edit and delete operations : the edit will be a link , and the delete will be a button to see how different is the model on the two implementations.

The list page now looks like this:

<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisherList.aspx.cs" Inherits="frmPublisherList" Title="Publisher Lists" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

    <asp:GridView ID="grdPublisher" runat="server" AutoGenerateColumns="false">

        <Columns>

            <asp:BoundField DataField="Site" HeaderText="Site" />

            <asp:BoundField DataField="Name" HeaderText="Name" />

            <asp:TemplateField HeaderText="Operations">

                <ItemTemplate>

                    <asp:Button runat="server" ID="btnDelete" CommandName="deletepub" CommandArgument='<%# Eval("IDPublisher") %>' Text="Delete" />

                    <asp:HyperLink runat="server" ID="hkEdit" NavigateUrl='<%# Eval("IDPublisher","~/frmPublisher_Edit.aspx?ID={0}") %>' Text="Edit"></asp:HyperLink>

                </ItemTemplate>

            </asp:TemplateField>

        </Columns>

   

    </asp:GridView>

    <br />

    <asp:Button ID="btnNew" runat="server" Text="New" OnClick="btnNew_Click" />

</asp:Content>

 

The link hkEdit is self explanatory – it goes to the frmPublisher_Edit.aspx with the ID of publisher in the row.

For the button we must create the event – and the event is on the grid itself – is the RowCommand

On the .cs file:

    protected void grdPublisher_RowCommand(object sender, GridViewCommandEventArgs e)

    {

        switch(e.CommandName)

        {

            case "deletepub":

                int idPublisher;

                if(int.TryParse(e.CommandArgument.ToString(),out idPublisher))

                {

                    Response.Redirect("frmPublisher_Delete.aspx?ID="+ idPublisher, false);

                    return;

                }

                Response.Write("Can not find id:" + idPublisher);

                break;

            default:

                Response.Write("Do not know command : " + e.CommandName);

                break;

        }

    }

 

Now create the two pages frmPublisher_Delete and frmPublisher_Edit 

On both we will copy the table from the new page and the source – without the class declaration. One more thing is to retrieve from ID the editing publisher:

 

  int idPublisher;

        if(!int.TryParse(Request.QueryString["ID"],out idPublisher))

        {

            Response.Redirect("frmPublisherList.aspx", false);

            return;

        }

        //we have id of the publisher

 

How can we retrieve from the ID of the publisher  the object ? Remember that in Windows forms application we did pass from one form to another the publisher object. Here we have just the Id. For this, we will open again the Book.sln solution and add the method to load one single object.

I like to put the method on ColPublisher and make it static … to not apparently create a new object.

 

public static Publisher sLoadFromID(int ID)

        {

            DbConnection db = Settings.TheConnection;

            using (db)

            {

                db.Open();

                IDataReader ir = Settings.Load("select IDPublisher, NamePublisher, SitePublisher from Publisher where IDPublisher="+ ID, db);

                while (ir.Read())

                {

                    Publisher p = new Publisher();

                    p.FillObject(ir);

                    return p;

                }

            }

            return null;

        }

 

Compile and go to Web project.We can have the publisher:

//we have id of the publisher

        Publisher p = ColPublisher.sLoadFromID(idPublisher);

        if (p == null)//maybe someone deleted

        {

            Response.Redirect("frmPublisherList.aspx", false);

            return;

        }

        if (!IsPostBack)

        {

            //now fill the text boxes

            txtName.Text = p.Name;

            txtSite.Text = p.Site;

        }

 

Why we have put  (!IsPostBack ) ? Simply because the textboxes must be filled only once – the first time. When the user enter new name and/or new site and after clicks on save, we must preserve his data .Other problem is that when we have to save the data, we must have the same code to load the publisher – so we put this into a function into the page:

private Publisher pub

    {

        get

        {

            int idPublisher;

            if (!int.TryParse(Request.QueryString["ID"], out idPublisher))

            {

               

                return null;

            }

            //we have id of the publisher

            return ColPublisher.sLoadFromID(idPublisher); ;

           

        }

    }

 

The code on PageLoad will be now shorter :

protected void Page_Load(object sender, EventArgs e)

    {

        Publisher p = pub;

        if (p == null)

        {

            Response.Redirect("frmPublisherList.aspx", false);

            return;

        }

 

        if (!IsPostBack)

        {

            //now fill the text boxes

            txtName.Text = p.Name;

            txtSite.Text = p.Site;

        }

    }

 

And we must modify the code on saving also :

protected void btnSave_Click(object sender, EventArgs e)

    {

        Publisher p = pub;

        if (p == null)

        {

            //TODO : throw an exception that someone deleted the publisher

            Response.Redirect("frmPublisherList.aspx", false);

            return;

 

        }

 

        p.Name = txtName.Text;

        p.Site = txtSite.Text;

        p.Update();

        Response.Redirect("frmPublisherList.aspx", false);

    }

 

 

You can modify also the text of btnsave from “Insert” to “Save”

On the delete page we will put the same code to retrieve the Publisher .Here is the code:

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using BookObjects;

 

public partial class frmPublisher_Delete : System.Web.UI.Page

{

    private Publisher pub

    {

        get

        {

            int idPublisher;

            if (!int.TryParse(Request.QueryString["ID"], out idPublisher))

            {

 

                return null;

            }

            //we have id of the publisher

            return ColPublisher.sLoadFromID(idPublisher); ;

 

        }

    }

    protected void Page_Load(object sender, EventArgs e)

    {

        Publisher p = pub;

        if (p == null)

        {

            Response.Redirect("frmPublisherList.aspx", false);

            return;

        }

 

        if (!IsPostBack)

        {

            //now fill the text boxes

            txtName.Text = p.Name;

            txtSite.Text = p.Site;

        }

    }

    protected void btnSave_Click(object sender, EventArgs e)

    {

        Publisher p = pub;

       

        if(p != null)

            p.Delete();

 

        Response.Redirect("frmPublisherList.aspx", false);

    }

    protected void btnCancel_Click(object sender, EventArgs e)

    {

        Response.Redirect("frmPublisherList.aspx", false);

    }

}

 

 

Do not forget to change the text “Insert” of btnSave to “Delete”. You also can put readonly property to true on the textboxes

<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisher_Delete.aspx.cs" Inherits="frmPublisher_Delete" Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

    <table>

        <tr>

            <td colspan="2">Enter values

            </td>

        </tr>

        <tr>

            <td>

               Name

            </td>

            <td>

                <asp:TextBox ID="txtName" runat="server" ReadOnly="true">

                </asp:TextBox>

            </td>

        </tr>

        <tr>

            <td>

               Site

            </td>

            <td>

                <asp:TextBox ID="txtSite" runat="server" ReadOnly="true">

                </asp:TextBox>

            </td>

        </tr>

        <tr>

            <td><asp:Button ID="btnSave" Text="Delete" runat="server" OnClick="btnSave_Click" />

            </td>

            <td><asp:Button ID="btnCancel" Text="Cancel" runat="server" OnClick="btnCancel_Click" />

            </td>

        </tr>

    </table>

</asp:Content>

 

 

Next time we will put some modifications to the site: a site map(in order to can have indications for the user where he is)  and code to change and load resources in English and French languages at run time.

 

.NET | ASP.NET | programare | tutoriale
Sunday, February 04, 2007 10:49:59 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Thursday, January 18, 2007


cu ce m-am mai batut in ultimul timp
cu optimizare aplicatie sa mearga mai repede - si am reusit sa gasesc articolul asta
http://www.mostlylucid.co.uk/archive/2003/12/09/664.aspx

in care spune ca intr-un gridview e mai rapid sa faci conversia la obiect + proprietati decit eval -care foloseste late binding

adica - folositi asta
  <asp:Label ID="lblNume" runat="server" Text='<%# string.Format("iata {0}",((obiect)Container.DataItem).nume) %>' ></asp:Label>

in loc de asta

<asp:Label ID="lblNume" runat="server" Text='<%# Eval("nume","iata {0}") %>'></asp:Label>

M-am mai batut cu property grid si cu ICustomTypeDescriptor - si am observat ca property grid cheama
GetProperties(Attribute[] attributes) - cu atributul browsable - iar un dropdownlist binduit cheama GetProperties() simplu ( de ce il cheama - iata o minune - probabil vrea sa se asigure ca exista proprietatile inainte de a le chema ...)
Concluzia : implementati GetProperties(Attribute[] attributes)  pentru un property grid cit mai bun si GetProperties() lasati-l cit mai simplu pentru asp.net

.NET | ASP.NET | programare
Thursday, January 18, 2007 3:56:45 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Friday, January 12, 2007


LINQ si linkuri
Dupa discutia de pe RONUA, in care Alex recomanda citirea http://blogs.msdn.com/ericwhite/pages/FP-Tutorial.aspx , am incercat sa pricep.

Tot RONUA mi-a fost de folos, Cryogenic si Alex recomandindu-mi 2 video-uri:
http://channel9.msdn.com/showpost.aspx?postid=114680.
http://channel9.msdn.com/ShowPost.aspx?PostID=236745#236745
( de vizualizat in ordinea asta - chiar daca se repeta)

Iar daca nu stiti (aproape) nimic despre FP( functional programming), Stalker mi-a trimis un link super bun:
http://www.defmacro.org/ramblings/fp.html

Multumesc tuturor!

.NET | LINQ | programare
Friday, January 12, 2007 8:49:19 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Sunday, December 17, 2006


P6 - setup program

Now to the performing of the setup.We suppose that we want to deploy from a CD.

 

Right click Book win project, choose properties, and click on “Publish” tab.

There you will find the “Publishing location” – default to http://localhost/BookWin/

If you do not have IIS, then you can select a path, like C:\Book\BookSetup\

The problem that we have is that in the files that we need to install must be also the mdb file.

If you have something like a VS.NET Standard(or more) you have a special project template that allows you to add other files to the deployment. For the moment, we have to do what we can do. So, please right click the bookwin project, click add=>existing item and search for  the book.mdb file from C:\Book\BookData .

Compile the project (CTRL+Shift+B) and now you will find the book.mdb on the application files – as data file.

Now to the prerequisites : Because we are deploying a CD, it is better to include .NET 2.0 – and download from the same location (when  we are deploying from internet, I think it is preferable to deploy from MS site )



The updates will not be yet available, since we do not have yet a web site. But we can customize some of  Options, like publisher name, product name and others.

 

Now press Publish Wizard :

            The first step is where to make the setup kit (C:\Book\BookSetup\ already selected ) , the next is from where (click “from cd –rom or dvd rom”).

            The third allows the application to check for updates – but , for the moment, we do not have a WebSite yet, so “the application will not check for updates”

            And press finish!

 

If an error occurs, that says that can not find package, please go to Microsoft .NET Framework Version 2.0 Redistributable Package (x86) http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5&displaylang=en  and download the kit. Copy this kit to <C:\Program Files>\Microsoft Visual Studio 8\SDK\v2.0\Bootstrapper\Packages\DotNetFX

For instmsia.exe , goto http://go.microsoft.com/fwlink/?LinkId=37285 

 

Now you can write the folder C:\Book\BookSetup to a CD and test .

If you do not want a CD, you can wrote a file and load as a CD.

One  way is to  create a ISO file with Alex Feinman IsoRecorder

http://isorecorder.alexfeinman.com/isorecorder.htm

Download his software ( I have tested the version for XP SP2 ) and right click the folder Book Setup








You will see Create ISO image file – click and accept default setting.

Now you have a CD  -and you can load this CD with  Virtual CD Control Panel.

 

You can now test the CD you have already created.

More, if you want to test on another environment, you can download Virtual PC 2004 SP1 or VMWare and create with those a new Windows Installation (of course, you must have the Windows installation CDs).

 

Next time we will do a ASP.NET application with SQL Server as a backend.

Suggested readings:

            Comparison between VS.NET 2005 editions: http://msdn.microsoft.com/vstudio/products/compare/default.aspx

            Virtual PC 2004 SP1 (free) http://www.microsoft.com/downloads/details.aspx?familyid=6d58729d-dfa8-40bf-afaf-20bcb7f01cd1&displaylang=en

            Deployment problems : http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=13937&SiteID=1

            Virtual CD Control Panel –  http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe

            Alex Feinman – Make ISO http://isorecorder.alexfeinman.com/isorecorder.htm

           

.NET | programare | tutoriale
Sunday, December 17, 2006 10:04:05 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Friday, December 15, 2006


regional settings, Excel ,CSV si OleDbConnection
Nebunul de excel, cind salveaza sub csv, tine seama de regional settings.Iar la mine List separator este ; (ca in Romana) - nu virgula( deci csv nu mai e comma separated values)

Asa se face ca la mine pe masina cind vreau sa citesc cu driver-ul de OleDbConnection(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strDir + ";Extended Properties='Text;HDR=NO;FMT=Delimited'") vrea neaparat virgula - si habar nu are ca sunt mai multe coloane...si intra in nebunie...
Dar cum s-ar rezolva nu stiu

.NET | programare
Friday, December 15, 2006 10:52:31 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback




Implement Interface - varianta 1
A trebuit sa fac IDisposable pentru Excel... si sa implementez toate Interfetele respective.
Normal ca a trebuit sa fac un program pentru asta... ca doar nu era sa le fac pe toate de mina-  si a iesit cam asa ceva
Presupun ca poate fi modificat destul de usor ca sa faca acelasi lucru pentru clase abstracte... dar inca nu am pofta si timp sa il termin

.NET | programare
Friday, December 15, 2006 5:17:59 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Thursday, December 07, 2006


Excel si C#
Dupa ce m-am batut cu referintele COM ( care mor imediat daca e proiect consola, dar care mai traiesc daca e ASP.NET) am reusit sa implementez IDisposable peste (aproape) fiecare obiect de la Excel.
Astfel incit am un Range_Disposable care inglobeaza / deriveaza din Range, un WorkSheet_Disposable care inglobeaza/deriveaza din Worksheet ( si la care metoda get_Range intoarce Range_Disposable).

Observatie 1.
    In proiectul consola, daca inchid Excel ( app.Quit(); Marshal.ReleaseComObject()) si am citeva Range_Disposable la care nu am aplicat Dispose, atunci app.Quit le apeleaza si pe ele.
    In proiectul ASP.NET , daca fac acelasi lucru, app.Quit da Access Denied...

Observatia 2.
    Totul se poate repara usor , folosind binecunoscutul using(Range_Disposable r = W.get_range())



programare | Excel | .NET
Thursday, December 07, 2006 10:19:45 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  |  Trackback


Theme design by Jelle Druyts

Pick a theme: