Woord vooraf - Download Now DOC by L9paT0cR

VIEWS: 66 PAGES: 115

									Woord vooraf
Dit eindwerk is tot stand gekomen dankzij de hulp van de volgende mensen waarvoor ik hen
wil bedanken.

Ten eerste wil ik de heer Samuel Longueval bedanken omdat hij het mogelijk heeft gemaakt
mij als stagiair te laten beginnen bij de NMBS.

Ik bedank ook de heer Luc Frix, mijn stagebegeleider. Dankzij de uitstekende
samenwerking met hem; is mijn stage aangenaam en zonder problemen verlopen.

Ik bedank ook de heer Johan Roosen, de heer Frederic Tais, de heer Vincent Allard, de heer
Christophe Waardenburg, de heer Laurent Nullens en de heer Michel Staudinger omdat zij
altijd klaarstonden om mijn vragen te beantwoorden en me te helpen.

Ik dank ook de heer Jef Verhaegen, mijn eindwerkbegeleider voor zijn goede raad en zijn
hulp.
                                                                                          3



Samenvatting
Dit eindwerk beschrijft de ontwikkeling van een user interface voor de SPS Admin Tool. De
SPS Admin Tool is een deel van een groter project. Het groter project is SPS, wat staat voor
Simple Planning System. De mainframe spuwt ASCII bestanden uit. De SPS Admin Tool
leest deze bestanden in, converteerd deze en importeerd ze in een Oracle database. Deze
toepassing is toegankelijk via intranet

De ontwikkeling gebeurde in Visual Studio 2003. Er werdt gebruik gemaakt van het .Net
framework met ASP.Net en C# als programmeertaal en het besturingssysteem Windows XP.

Dit eindwerk beschrijft ook hoe ARTWEB werdt geoptimaliseerd. ARTWEB houdt de
vertragingen van treinen in real-time bij. Voor de optimalisatie waren er aanpassingen nodig
op drie niveau’s. Als eerste was er de normalisatie van de database, daarna de optimalisatie
van de stored procedures en als laatste een aanpassing van de interface.

De ontwikkeling gebeurde in ASP op een PC met Windows NT 4.0 als besturingssysteem.
Ook ARTWEB gebruikt een Oracle database om gegevens te bewaren. Deze toepassing is
ook toegankelijk via intranet.
                                                                                                                                4



Inhoudsopgave

Woord vooraf ...................................................................................................... 2

Samenvatting ....................................................................................................... 3

Inhoudsopgave .................................................................................................... 4

Alfabetische lijst van de gebruikte afkortingen .................................................. 6

Inleiding .............................................................................................................. 7

1.      Omschrijving van de NMBS ...................................................................... 8
1.1     Geschiedenis van de NMBS ............................................................................... 8
1.2     Doelstellingen van de NMBS ............................................................................. 8
1.3     Organigram ......................................................................................................... 9
1.4     Information Technology/Telecom .................................................................... 10

2.      Project SPS Admin Tool .......................................................................... 13
2.1     Inleiding ............................................................................................................ 13
2.2     Problemen met de huidige situatie .................................................................... 13
2.3     Doelstellingen ................................................................................................... 14
2.4     Gebruikte technologie ....................................................................................... 14
2.5     Projectorganisatie .............................................................................................. 15
2.6     Projectopdracht ................................................................................................. 16
2.7     Planning............................................................................................................. 18
2.8     Voorbereidend onderzoek ................................................................................. 18
2.9     Praktische uitwerking ........................................................................................ 22

3.      Handleiding G153 (SPS) Admin Tool ..................................................... 59

4.      Project Artweb .......................................................................................... 65
4.1     Inleiding ............................................................................................................ 65
4.2     Projectopdracht ................................................................................................. 67
4.3     Projectorganisatie .............................................................................................. 68
4.4     Planning............................................................................................................. 68
4.5     Voorbereidend onderzoek ................................................................................. 69
4.6     Functionele aanpassing ..................................................................................... 69
4.7     Praktische uitwerking ........................................................................................ 75
4.8     Resultaat ............................................................................................................ 76
4.9     Besluit ............................................................................................................... 81

5.      Handleiding ARTWEB onderdeel “Beheer Dossier” .............................. 82

Besluit ............................................................................................................... 90
                                                                                                                                        5

Bijlagen ............................................................................................................. 91

1.       BRail WebControls Developers Guide .................................................... 92
1.1      Distribution List ................................................................................................ 92
1.2      Version History ................................................................................................. 92
1.3      Audience ........................................................................................................... 93
1.4      Installation ......................................................................................................... 93
1.5      Controls in the assembly ................................................................................... 93

2.       BRail Localization Developer’s guide ................................................... 101
2.1      Distribution List .............................................................................................. 101
2.2      Version History ............................................................................................... 101
2.3      Audience ......................................................................................................... 102
2.4      Introduction ..................................................................................................... 102
2.5      Installation ....................................................................................................... 102
2.6      How-to use it ................................................................................................... 102
2.6.1 web.config .................................................................................................................. 102
2.6.2 Translation file............................................................................................................ 103
2.6.3 Using the component .................................................................................................. 104

3.      Exception Management Block - Developers Guide ................................ 106
3.1     Distribution List ............................................................................................... 106
3.2     Version History ................................................................................................ 106
3.3     Introduction ...................................................................................................... 107
3.4     Installation ........................................................................................................ 107
3.5     Exception class hierarchy................................................................................. 108
3.6     Exception Manager .......................................................................................... 109
3.7     Design .............................................................................................................. 110
3.8     Using the Exception Manager .......................................................................... 111
3.8.1 Basic publishing ......................................................................................................... 111
3.8.2 Publishing additional information .............................................................................. 111
3.8.3 Switching on/off a publisher ...................................................................................... 111
3.8.4 Using the Default Publisher........................................................................................ 112
3.8.5 Using multiple publishers ........................................................................................... 112
3.8.6 Filtering ...................................................................................................................... 113
3.9 Best Practices ................................................................................................... 113
3.10 Useful technical information ............................................................................ 114
3.11 Using the config settings .................................................................................. 114
3.11.1 Publisher Elements Quick Reference: ...................................................................... 114
3.12 Future ............................................................................................................... 115
3.12.1 Publishers ................................................................................................................. 115
3.12.2 Event monitor ........................................................................................................... 115
3.12.3 Code skeleton injections ........................................................................................... 115

Bibliografie ..................................................................................................... 116
                                                    6


Alfabetische lijst van de gebruikte afkortingen

AD           Afdeling
AS           Algemeen Secretariaat
ASP          Active Server Pages
BSM          Business System Manager
CO           Communicatie
DB           DataBase
DBA          DataBase Administrator
DOS          Disk Operating System
GB           Gedelegeerd Bestuurder
GEN          Gewestelijk Express Net
GUI          Graphical User Interface
HTML         Hyper Text Markup Language
ICT          Information Communication Technology
IIS          Internet Information Server
IMI          Interface Met Infrastructuur
IT-TE        Information Technology & Telecom
JZ           Juridische Zaken
             Nationale Maatschappij der Belgische
NMBS         spoorwegen
OCC          Oracle Competent Center
OO4O         Object Oriented For Oracle
S&O          Strategie en Ontwikkeling
SPS          Simple Planning System
SQL          Structured Query Language
TCT          Technische Cellen Treinen
TGV          Train a Grand Vitesse
TNM          Trein Nummer Melding
                                                                                         7



Inleiding
Gedurende mijn stage ging ik, als stagiair-programmeur bij de NMBS, de ontwikkeling van
project Mandharin doen. Omdat de klant niet tevreden was over de analysedocumenten,
werd er een No Go gegeven, waardoor ik niet aan het porject Mandharin kon werken. Ter
vervanging heb ik twee andere projecten afgewerkt.

Ik heb de interface voor de SPS Admin Tool ontwikkeld. Deze interface is ontwikkeld in
Visual Studio 2003 volgens het .Net framework. De SPS Admin Tool is een webtoepassing
die zal draaien op een IIS server 6.0. De gebruikers zullen toegang krijgen tot deze
applicatie via Internet Explorer 6.0. De SPS Admin Tool leest bestanden in van het
mainframe en importeert deze in een Oracle database. SPS staat voor Simple Planning
System. De SPS Admin Tool is een onderdeel van de SPS webtoepassing, dat zal instaan
voor het beheer van diensttabellen en uurroosters van al het rijdende personeel. In deze
diensttabellen en uurrooster staan de werk- en verlofuren van zowel de treinbestuurders als
de treinbegeleiders.

Ook heb ik het onderdeel “Beheer Dossier” van ARTWEB geoptimaliseerd. ARTWEB is
geprogrammeerd in ASP. ARTWEB draait op IIS 6.0 en de gebruiker kan toegang krijgen
met Internet Explorer vanaf 5.5. ARTWEB is een toepassing die treinvertragingen
registreert. Een treinvertraging kan verschillende oorzaken hebben.

Maar vooraleer ik deze projecten uitleg zal ik een omschrijving geven van de NMBS.
                                                                                            8



1.       Omschrijving van de NMBS

1.1      Geschiedenis van de NMBS

De NMBS (Nationale Maatschappij der Belgische spoorwegen) is een naamloze
vennootschap volgens publiek recht.

In 1926 werd de NMBS opgericht om het spoorvervoer uit te baten op het Belgische
spoorwegnet, één van de dichtste netten in Europa.

De onderneming is actief op drie gebieden:

        Het personenvervoer binnen de landsgrenzen (openbare dienstverlening)
        Het internationale reizigersvervoer (klassieke treinen, Eurostar, Thalys, TGV)
        Het goederenvervoer


De NMBS is eveneens heel actief op het vlak van telecommunicatie: de onderneming werkt
aan de commercialisering van een eigen glasvezelnetwerk.

In 2002 heeft de NMBS haar structuren gereorganiseerd met het oog op een grotere
efficiëntie. De Belgische spoorwegen zijn onderverdeeld in 10 directies, die elk economisch
en financieel verantwoordelijk zijn voor hun producten en specifieke actieterreinen, waarbij
de synergie met de andere eenheden bewaard blijft.




Figuur 1.1 Logo NMBS



1.2      Doelstellingen van de NMBS

De NMBS hecht veel belang aan de modernisering van haar spoorwegnet. De modernisering
verloopt via de uitvoering van opeenvolgende meerjarenplannen, die worden bijgesteld in
functie van de noden en de middelen. In de loop van de volgende twaalf jaren ( periode
2001 – 2012) zal ongeveer 17,7 miljard euro worden besteed aan de verbetering van haar
infrastructuur en diensten.

De doelstellingen zijn:

        Modernisering van de belangrijkste reiziger - en goederen assen
        Vernieuwing van het bestaande materieel en aankoop van nieuwe treinen
        De uitbouw van een hogesnelheidsnet van grens naar grens:
                                                                                  9

      Brussel – Franse grens
           Brussel – Duitse grens
           Brussel – Nederlandse grens

      Ontwikkeling van de infrastructuren rond de nationale luchthaven
      Verbetering van de toegankelijkheid van de havengebieden


1.3            Organigram




Figuur 1.2 Structuur van de NMBS


NMBS structuur

De structuur van de NMBS bestaat uit 10 Algemene Directies, aangevuld met 6
stafdiensten. De 10 Algemene Directeurs komen samen onder het voorzitterschap van de
Gedelegeerd Bestuurder, Karel Vinck.


De taakverdeling onder de leden van het directiecomité is de volgende:
    Algemeen Directie Operaties: Antoine Martens
    Algemeen Directie Financiën: Luc Lallemand
    Algemeen Directie Resources: Tony Van Den Berghen
    Algemeen Directie Goederen: Marc Descheemaecker
    Algemeen Directie Reizigers: Leo Pardon
    Algemeen Directie Materieel: Jean Denayer
    Algemeen Directie Treinen: Daniel Derochette
    Algemeen Directie Netwerk: Alex Migom
                                                                                        10

       Algemeen Directie Infrastructuur: Jean-Marie Raviart
       Algemeen Directie Patrimonium: Vincent Bourlard

De 6 stafdiensten zijn:

       Strategie en Ontwikkeling
       Communicatie
       Juridische Zaken
       Algemeen Secretariaat
       Information Technology / Telecom
       Gewestelijk Express Net


1.4              Information Technology/Telecom




Figuur 1.3 Structuur van ICT


Beschrijving van de diensten en de afdelingen

ICT.4

“Netwerk” staat garant voor het central beheer van de investeringsprojecten die betrekking
hebben op de telecommunicatie.

Deze dienst in samengesteld uit twee afdelingen:

       ICT.41
                 “Basisnetwerk” is verantwoordelijk voor de werken die relatief zijn aan de
                 basisinfrastructuur.

       ICT.42
                 “Netwerk met toegevoegde waarde” ontwerpt alle communicatiesystemen die
                 boven op de basisinfrastructuur worden geplaatst.
                                                                                           11

ICT.5

“Projecten” beheert alle projecten met betrekking tot de informatisering van de
bedrijfsprocessen van de NMBS.


Deze dienst is onderverdeeld in 3 afdelingen:

       ICT.51
                 “Design” staat in voor de definitie en de opstelling van de technologische
                 architectuur op dewelke de verschillende applicaties die ontwikkeld zijn door
                 de stafdienst ICT berusten.

       ICT.52
                 “Projectenbeheer” draagt de verantwoordelijkheid voor het beheer van de
                 verschillende informatiseringprojecten. Deze afdeling voert natuurlijk ook
                 functionele en technische analyses uit die nodig zijn voor de ontwikkeling
                 van de door de klanten gevraagde applicaties. Dit is de afdeling waar ik mijn
                 stage heb gelopen.

       ICT.53
                 “Beheer van de Competentie Centra” bestaat, zoals de naam het al zegt uit
                 verschillende Competentie Centra. Deze staan in voor het beheer van de
                 personen die helpen bij de ontwikkeling of bij de implementatie van de
                 applicaties die worden gemaakt om aan de behoeften van de klanten te
                 voldoen.


ICT.6

“Exploitatie” verzekert de exploitatie van de verschillende systemen, zowel inzake
informatica als telecommunicatie, die ter beschikking staan van de eenheden van de NMBS.

Deze dienst rekent op twee afdelingen om de continuïteit van het beheer van het bedrijf en
zijn verschillende processen te verzekeren.

       ICT.61
                 “Exploitatie ICT” is verantwoordelijk voor de monitorring en waakt over het
                 geheel van de systemen (netwerk, mainframe, unix,…)

       ICT.62
                 “Ondersteuning van de exploitatie” beschikt over een aantal middelen die de
                 afdeling ICT.61 toelaten om zijn werk in de beste omstandigheden uit te
                 voeren.


ICT.7

“Klantendienst” is onderverdeeld in twee afdelingen.
                                                                                          12

      ICT.71
                “Producten en diensten”, heeft als doel te waken over de tevredenheid van de
                klanten en over het respecteren van de verschillende niveaus van diensten die
                met hen worden overeengekomen.

      ICT.72
                “Werken en ondersteuning”, omvat de uitvoerende diensten en coördineert
                het werk dat wordt verricht in de zones.

Naast deze vier diensten bestaan er twee afdelingen en twee bureaus die onmiddellijk
afhangen van de General Manager.

Bureau’s:

      ICT.001
             “Strategie en kwaliteit”. Dit bureau dekt alle activiteiten met betrekking tot
             de invoering en de opvolging van de strategie van de ICT evenals deze
             betreffende de kwaliteit en de beveiligingspolitiek.

      ICT.002
             “Commerciële activiteiten” is belast met het commercieel beheer van alle
             activiteiten die de stafdienst ICT verricht voor derden die geen deel uitmaken
             van de NMBS groep.

Afdelingen:

      ICT.03
                “Beheer van de relaties & het financieel beheer” staat niet alleen in voor de
                contacten met de interne klanten van de NMBS, maar ook voor het financieel
                beheer van de eenheid. Het is dus deze afdeling die verantwoordelijk is voor
                het beheer van de budgetten, het beheer van de contacten en het beheer van
                de facturen.

      ICT.08
                “Administratie & Human Resources” is belast met het beheer van het
                personeel alsook de interne en externe communicatie.
                                                                                          13



2.     Project SPS Admin Tool

2.1            Inleiding

Dit deel heeft betrekking op het project dat ik heb uitgevoerd tijdens mijn stage bij de
NMBS. Dit project kadert binnen de SPS (Simple Planning System) toepassing.
SPS is een toepassing die zal worden gebruikt voor het opstellen van diensttabellen van de
treinbestuurders en de treinbegeleiders. Een diensttabel is een werkrooster voor het rijdende
personeel. Het rijdende personeel kan zowel de treinbestuurder als de treinbegeleider zijn.
SPS gaat de huidige applicatie editts.exe vervangen. Editts.exe is een DOS toepassing
gerealiseerd in Turbo-Pascal. Ook zal er een Admin Tool ter beschikking gesteld worden
die de bestanden van de mainframe importeert naar een database. Enkel de Admin Tool valt
binnen de scope van dit document.


2.2            Problemen met de huidige situatie

De huidige manier van werken gaat gepaard met een aantal problemen. Dit project dient om
deze problemen op te lossen.

De huidige applicatie EDITTS.EXE is een DOS toepassing gerealiseerd in TURBO-PASCAL. Er
heerst grote onzekerheid over de ondersteuning voor DOS toepassingen in toekomstige
versies van het WINDOWS besturingssysteem.

De A3-printers, welke momenteel gebruikt worden voor het afdrukken van rapporten (E500,
E505, Maaltijdcheques,…) zijn aan vervanging toe. In de programmacode van EDITTS.EXE
werd echter gebruik gemaakt van stuurcodes specifiek voor dit type printer. De vervanging
van deze printers impliceert dus het aanpassen van al deze stuurcodes. Eerdere pogingen om
een dergelijke aanpassing uit te voeren mislukten. Noch ICT, noch Directie Treinen
beschikt over resources met een grondige kennis van de programmeertaal TURBO-PASCAL.

Er bestaat in de huidige situatie geen centrale databank. Als eerste gevolg hiervan moet elke
wijziging aan de referentiegegevens door Directie Treinen worden doorgegeven aan de
betrokken TCT’s (Technische Cellen Treinen), welke op hun beurt de aanpassingen lokaal
dienen te implementeren. Bovendien kan Directie Treinen met het huidige systeem op geen
enkel ogenblik de situatie op het terrein bekijken.

Editts.exe maakt bij het opstellen van de diensttabellen gebruik van personeelsgegevens
welke aangevoerd worden door een ander DOS-programma (SIGNALET.EXE). Deze
toepassing wordt op zeer korte termijn vervangen door de web-applicatie KARMA. KARMA
valt buiten de scope van dit document.

De huidige toepassing geeft onvoldoende grafische mogelijkheden zodat de planners hun
planning niet onmiddellijk op het scherm kunnen uitvoeren. Dit scherm geeft dus op geen
enkel moment een volledig overzicht van het dienstverloop voor meerdere bestuurders in
functie van de tijd. De huidige werkwijze van de planners bestaat er dus in om eerst de
diensttabellen af te drukken, hierna de nodige wijzigingen en/of vervangingen met de hand
uit te voeren, om deze tenslotte in het systeem in te brengen.
                                                                                        14


Het huidige systeem mist flexibiliteit om vlot te kunnen werken in het geval dat er in de
loop van de te plannen periode aanpassingen gebeuren aan de uurregelingen tengevolge van
speciale periodes of feestdagen (toeristische periode, winterperiode,….).


2.3           Doelstellingen

Algemeen gesteld moet het nieuwe informatiesysteem aan de volgende doelstellingen
voldoen:

      Op korte termijn EDITTS.EXE vervangen
      Toegang via Intranet
      Overname van de gegevens A205

Editts.exe zal worden vervangen door een toepassing die gebouwd wordt met hedendaagse
technologieën waarbij de gegevens via een centrale databank beheerd worden.

SPS staat ter beschikking van het Hoofdbestuur van Directie Treinen en van de TCT’s
(Technische Cellen Treinen). Aangezien deze gebruikers geografisch sterk verspreid zijn, is
het aangewezen om de applicatie toegankelijk te maken via het Intranet van de NMBS.
Voordeel van dergelijke aanpak is tweeërlei:
     Voor de applicatiebeheerder:
          o Centraal beheer van de toepassing: elke installatie of aanpassing van de
              applicatie is onmiddellijk en voor iedere gebruiker beschikbaar. Er dienen
              geen installaties ter plaatse te gebeuren.

      Voor de gebruikers:
          o Door SPS te ontwikkelen als een webtoepassing is een naadloze integratie
             mogelijk met andere webtoepassingen zoals bijv. Karma. De gebruiker zal
             zich zo sneller vertrouwd voelen met de nieuwe toepassing (dezelfde ‘look
             and feel’)

Om snel een werkende toepassing te kunnen bouwen zal een administrator-tool gebouwd
worden, welke de flatfiles inleest en deze nadien overzet naar een centrale ORACLE-
databank. Deze flatfiles worden gegenereerd vanuit de databank A205. Deze Admin Tool is
een tussenstap tussen de A205 mainframe en de SPS toepassing. Dit is gedaan omdat de
ontwikkeltijd zeer kort is. In de toekomst zal SPS rechtstreeks met het mainframe
communiceren.

Enkel de SPS Admin Tool valt binnen de scope van dit deel.


2.4           Gebruikte technologie

De webapplicatie zal ontwikkeld worden door gebruik te maken van onderstaande
technologieën:

Webapplicatie ontwikkeld binnen ontwikkelplatform MICROSOFT. NET2003
De applicatie draait op een Windows2003 applicatie-server.
                                                                                15

Gecentraliseerde ORACLE-Databank
Gebruikers werken met de toepassing door middel van een webbrowser (INTERNET
EXPLORER) en een intranettoegang

Schematisch kunnen we de technische architectuur aldus voorstellen:




Figuur 2.1 Gebruikte technologie



2.5             Projectorganisatie

                                   BSM (Business System        E. Lips
                                   Manager)
                                   Sponsor                     F. Cornu
                                   Coach project               G. Steuperaert
                                   Project leader + Business   P. Schippers
                                   expert
                                   Key-users                   I. Degroote
                                                               P. Dignef
                                   Program Manager             S. Longueval
                                   Project Leader              L. Frix
                                   Business Analyst            E. Coopman
                                   Development Team            J. Roossen
                                                               V. Allard
                                                               A. Skupiewski
                                                               M. Staudinger
                                                               N. Gees
                                                               J. Ronsse
                                                               J-M Pignon
                                                                                         16


Schematisch kunnen we de projectorganisatie als volgt voorstellen.

                            BSM
                           E. Lips


  Project coach           Sponsor         Business expert
  G. Steuperaert          F. Cornu         P. Schippers


                          Key Users
                         I. Degroote
                          P. Dignef


                       Program manager
                         S. Longueval


                        Project leader
                            L. Frix


                       Business Analyst
                         E. Coopman


                      Development team
                          J. Roosen
                           V. Allard
                        A. Skupiewski
                        M. Staudinger
                           N. Gees
                           J. Ronse
                         J-M Pignon


Figuur 2.2 Projectorganisatie



2.6                Projectopdracht

Ik heb de opdracht gekregen een interface te maken voor de SPS Admin Tool. De interface
gebruikt het .NET framework van Microsoft. De interface is ontwikkeld met behulp van
Microsoft Visual Studio 2003. Als programmeertaal word C# gebruikt. Ook wordt het .NET
framework gebruikt om de pagina’s in te delen. Als de interface af is, begint het integreren
van de onderdelen. De onderdelen zijn het importeren van de bestanden en het maken van
een databaseconnectie. Maar deze onderdelen zijn door andere mensen geprogrammeerd. Zo
moet ik enkel de onderdelen gebruiken die ik ga ontvangen.

Omdat er al een interface bestond voor de SPS Admin Tool maar dan voor een client-server
toepassing heb ik wat inspiratie gevonden bij de schermen van deze interface. Maar omdat
de toepassing een Webtoepassing wordt, moest de indeling en het aantal schermen
veranderd worden. Dit wordt in een volgende paragraaf uitgelegd. Hierna volgen de
schermen van de Client-server toepassing.

Prestatie en reeks scherm: Hier kan de gebruiker prestaties of reeksen importeren.

Periode scherm: Hier kan de gebruiker een periodebestand inkijken zoals een preview.
                                                                                   17

Monitorscherm: Hier kan de gebruiker volgen of het importeren gelukt is of niet.




Figuur 2.3 Monitorscherm




Figuur 2.4 Periodescherm
                                                                                      18




Figuur 2.5 Rapportscherm



Deze schermen moet ik omzetten naar een ASP.NET Web toepassing.


2.7            Planning

Onderdeel                                 Datum
Initialisatie SPS project                 30/03/2004
Introducing to C# programming             31/03/2004 tot 03/04/2004
(Cursus doorgenomen)
Programming with the .net framework       03/04/2004 tot 05/04/2004
(Cursus doorgenomen)
Developing ASP.NET                        05/04/2004 tot 08/04/2004
(Cursus doorgenomen)
Ontwikkeling van GUI                      08/04/2004 tot 01/05/2004
Integratie van Import procedures          02/05/2004 tot 06/05/2004
Testen van de applicatie                  06/05/2004 tot 28/05/2004


2.8            Voorbereidend onderzoek

Omdat deze interface met een nieuwe technologie gemaakt is, heb ik de eerste dagen vooral
de cursussen van Microsoft nagekeken. De lijst van de cursussen kan u in de bibliografie
bekijken. Voor ik gestart ben met het programmeren, heb ik geschetst hoe ik het project
ging indelen.
                                                                                          19




Figuur 2.6 Indeling project


Ik heb mijn project ingedeeld in 1 solution. Een solution is een groepering van projecten.
Binnen deze solution zijn er vier projecten. Een project kan een groepering zijn van klassen,
webformulieren, enz.. In het project GUI staan alle webformulieren. In het database
connection project staan alle klassen die betrekking hebben op de databaseconnectie. In het
Import + Rapport project staan alle klassen over de import procedure en het Rapport dat
gegenereerd wordt. In DiskAccess moesten alle klassen komen die betrekking hebben op het
uitlezen van de file en het navigeren in de directorystructuur op de server. Maar omdat er
geen extra functionaliteiten toegevoegd werden, heb ik deze samengenomen met de GUI.

Nadat ik mijn schets is goedgekeurd, heb ik de solution en de projecten aangemaakt op mijn
PC. Bij de NMBS gebruiken ze een speciale naming convention.
Mijn solution noemt: BRail.G153.MainSolution. De naam bestaat uit drie delen. Het eerste
deel bestaat uit BRail (Belgium Rail). Dit is de engelse benaming voor NMBS. Het tweede
gedeelte is altijd de projectnaam. Hier is dat G153. Het laatste gedeelde is vrij te kiezen.
Mijn projecten heb ik als volgt benoemd met dezelfde naming conventions. De GUI is
BRail.G153.Import.GUI. De Database connection noemt BRail.G153.Import.Engine.
DBCon en het import + rapport noemt BRail.G153.Import.Engine.Import. De DiskAccess
zit in de GUI dus hiervoor is geen project gemaakt.

De databaseconnectie en de import vallen buiten de scope van dit document. Enkel de GUI
valt binnen de scope van dit document. Mijn opdracht bestond dan ook uit het maken van
een interface en het integreren van de onderdelen die door andere mensen zijn gemaakt. Er
                                                                                     20

wordt grondig getest tijdens de ontwikkeling maar ook nadien zodat men zeker is dat de
toepassing goed werkt.

Ik heb ook een schets gemaakt van hoe ik de schermen zou inrichten. Eigenlijk bestaat de
toepassing uit drie identieke schermen, een monitorscherm en een periodescherm.

Dit waren de eerste schetsen voor de interface:

De importschermen zouden er zo gaan uitzien:




Figuur 2.7 Importscherm


Het periodescherm zou er als deze gaan uitzien:




Figuur 2.8 Periodescherm
                                                                                        21

En het monitorscherm zou er zou gaan uitzien:




Figuur 2.9 Monitorscherm



Natuurlijk werd ik tijdens de ontwikkeling altijd door Johan Roosen bijgestuurd; Zodat de
interface er niet altijd zoals op de schets uitziet. Ik zal telkens de reden geven van de
verandering van de interface.

De verschillende importschermen gebruiken telkens verschillende bestanden die
geïmporteerd moeten worden. Ik heb ook de vorm van de bestandstypen gekregen die
schermen moeten gebruiken zodat er enkel deze bestanden zichtbaar zijn en geen andere
bestanden kunnen geselecteerd worden.

Voor prestatiebestanden zijn de volgende bestandtypen toegelaten: presthld.*, prestelc.* en
prestchg.*. Een prestatie is een chronologische opeenvolging van taken, uitgevoerd door een
bestuurder in 1 dienst.

Voor reeks bestanden zijn de volgende bestandtypen toegelaten: scon*.* en schg*.*. Een
reeks is een groepering van mensen die dezelfde kennis hebben op een bepaald gebied.

Voor infos bestanden worden enkel infos*.* toegelaten. Een infos is een hierarchische
structuur van depots en bestuurders.

Voor periode bestanden word er geen extensie gegeven. Een periode bevat een begin- en
einddatum met een beschrijving. Een periode geeft weer wanneer wel of geen
seizoentreinen rijdt.
Dit was het voorbereidende onderzoek. De volgende stap is de praktische uitwerking.
                                                                                          22

2.9            Praktische uitwerking

Met de praktische uitwerking wordt het ontwikkelen en programmeren van de interface
bedoeld. Hiervoor werd Visual Studio 2003 gebruikt. Ik heb de schermen getekend in VS
2003 en heb deze telkens laten nakijken door Johan Roosen. De uiteindelijke resultaten zijn
de volgende schermen.

Er zijn drie identieke schermen voor de import. Deze zien er als volgt uit:




Figuur 2.10 Importscherm prestatie


Hier kan de gebruiker een databaseserver en een databasenaam opgeven. Hij kan ook
navigeren via de boomstructuur van de mappen door op de listbox te klikken. Bestanden
selecteren kan door op de listbox van bestanden te klikken of door op het pijltje te klikken.
Bestanden verwijderen die geselecteerd zijn, kan door op de listbox van geselecteerde
bestanden te klikken of door op de knop met het vuilbakje te klikken. Het importproces
wordt gestart door op de knop Importeer bestanden te klikken.

Het periodescherm ziet er anders uit omdat men hier geen bestanden importeert maar enkel
een preview geeft van de inhoud van het bestand. Omdat de klassen voor deze preview niet
klaar zijn en door iemand anders geprogrammeerd worden valt dit buiten de scope van dit
document. Enkel de interface valt binnen de scope van dit document. Hier kan men gewoon
navigeren in de boomstructuur van de mappen.
                                                                                      23

Het scherm ziet er als volgt uit:




Figuur 2.11 Periodescherm


Indien er een importproces gestart is komt men op het monitorscherm terecht. Dit geeft de
stand van zaken van het importproces weer. Het scherm ziet er als volgt uit:
                                                                                    24




Figuur 2.12 Monitorscherm


Dit scherm wordt elke seconde vernieuwd zodat men altijd de laatste informatie over het
proces krijgt. Indien men het vinkje aanvinkt dan word het scherm niet meer vernieuwd,
zodat de gebruiker de meldingen kan lezen. Het proces wordt echter niet afgebroken. Als
men op de knop afbreken klikt dan keert men terug naar het importscherm en word het
proces afgebroken.

De werking van de hele toepassing is in het volgende schema weergegeven:




Figuur 2.13 Werking SPS Admin Tool
                                                                                        25


De mainframe spuwt bestanden uit in ASCII formaat. De SPS Admin Tool haalt leest deze
bestanden in en de gebruiker kan de database kiezen waar deze bestanden in geimporteerd
moeten worden. Dan start het SPS Admin Tool het importproces op. Tijdens deze
importproces wordt er gemonitort om te zien dat alles met succes verloopt. Is dit het geval
dan worden de gegevens geimporteerd naar de database.

Omdat ze bij de NMBS verschillende standaarden hebben om meer faciliteiten in de
toepassingen te stoppen, ga ik eerst de verschillende procedures bespreken.

De eerste procedure is het gebruik van BRailControls. Dit zijn controls die door de NDCC
gemaakt werden. Het NDCC is een groep van mensen die gespecialiseerd zijn in .NET.
Deze mensen hebben als verantwoordelijkheid het standaardiseren van de .NET
programmering. Door het ontwikkelen van procedures die door elke programmeur moeten
gebruikt worden.

De BRailControls worden geleverd als een installatiepakket. Als men deze installeert dan
moet men een nieuwe referentie toevoegen in Visual Studio 2003. Als dit gebeurd is dan
moet men in de toolbox een nieuw onderdeel toevoegen dat ook naar deze BRailControls
refereert. Vanaf nu kan men de BRailControls gebruiken. Het grootste voordeel is dat als er
een nieuwe en verbeterde versie uitkomt van deze componenten enkel het nieuwe
installatiebestand geïnstalleerd moet worden. Automatisch wordt de nieuwe versie gebruikt
zonder dat de code achter de componenten moet vernieuwd worden. In bijlage vindt u het
document dat over deze BRaiLControls handelt. Hier vindt u meer uitleg. Als voorbeeld zal
ik een gewone component en een BRailControl laten zien.

Dit is een BRailControl: <brailaspcontrols:BRailTextBox id="txtBut2" key="txtBut2"
runat="server" Visible="False"></brailaspcontrols:BRailTextBox>

Dit is een gewone component:             <asp:textbox   id="txtInvisText"   runat="server"
Width="649px"></asp:textbox>

De volgende procedure is het “BRail Exception Management Bloc” (EMB).

De EMB is gebaseerd op twee concepten:
        Exception base class hierarchy
        Exception Manager
Hoewel deze twee concepten in hetzelfde blok zitten, kunnen deze onafhankelijk van elkaar
gebruikt worden.

De EMB heeft als functionaliteit het automatisch afhandelen van excepties, in een
éénzijdige manier en het eenvoudig publiceren op verschillende plaatsen. De informatie die
wordt gepubliceerd bevat de basis .Net exceptie informatie, uitgebreide informatie van het
.Net framework en informatie die manueel toegevoegd werd door de ontwikkelaar.
De EMB gebruikt de volgende namespaces:
      BRail.FrameWork.ExceptionManagement.Common
      BRail.FrameWork.ExceptionManagement.Interfaces

Voor het installeren van de EMB moet men gewoon de installatiebestanden installeren. Als
dit gebeurd is dan moet men een nieuwe referentie maken in Visual Studio.
                                                                                                            26


Nu zal ik een aantal voorbeelden geven:

Voor de basispublicatie:

         Catch (DivideByZeroException ex)
         {
           BRailException newex = new BRailException (“Incorrect division”,ex) ;
           ExceptionManager.Publish (newex) ;
         }

We vangen een exceptie op met “Catch (DivideByZeroException ex)”. Daarna maken we
een nieuwe exceptie met “BRailException newex = new BRailException (“Incorrect
division”,ex) ;” Nu kan men deze publiceren met “ ExceptionManager .Publish (newex) ;”

Voor uitgebreide informatie over EMB kan u steeds het document in bijlage lezen.

Nu komen we aan de procedure van de Localization. Localization wil zeggen dat men de
applicatie in meerdere talen aanbiedt aan de gebruiker. Ik zal ook de verschillende stappen
uitleggen die nodig zijn om deze procedure te gebruiken.
Als eerste stap is de installatie van de installatiebestanden. Daarna refereren we in Visual
Studio naar deze bestanden. Daarna moeten we de “web.config” aanpassen.

<sectionGroup name="system.web">

<section     name="localizationsettings"      type="System.Configuration.NameValueFileSectionHandler,   System,
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

</sectionGroup>

Deze code moet bovenaan ingetypt worden. En onderaan moet de volgende code getypt
worden:

<localizationsettings>
          <add key="ResourceBaseName" value="trans.xml" />
          <add key="ResourceManagerKey" value="key" />
          <add key="ResourceManagerType" value="XmlFile" />
          <add key="ApplicationPath" value="D:\\PROJECTS\\BRail.G153.Import.GUI\\"/>
          <add key="TranslationFilePath" value="resources\\translation\\trans.xml" />
          <add key="ApplicationVariableName" value="XmlLocalization" />
          <add key="SupportedCultures" value="fr-be;nl-be;en-gb" />
</localizationsettings>

De ResourceBaseName is de naam van het XML bestand dat wordt gebruikt om de
verschillende talen te ondersteunen.
De ResourceManagerKey is de waarde die wordt gebruikt om alle objecten te
onderscheiden. Hier is dit “key” maar het kan evengoed “id” zijn.
Het ResourceManagerType geeft de verschillende types aan om de vertalingen op te halen.
Tijdens de ontwikkeling van de toepassing werd er enkel XmlFile ondersteund maar later
kan men de vertalingen altijd in een database bewaren.
Het ApplicationPath is het fysische pad van de webtoepassing.
Het TranslationFilePath is een pad waar het XML document staat.
De ApplicationVariableName is de naam van een applicatievariabele die wordt gebruikt om
gegevens over Localization te bewaren.
                                                                                                                27

De SupportedCultures is een lijst van talen die allemaal ondersteund worden.

Om Localization te gebruiken moet men ook iets aanpassen aan de HTML van de pagina. Ik
zal een voorbeeld geven van een component met - en een component zonder Localization:

         Zonder Localization:

<brailaspcontrols:braillabel id="lblDBServer" runat="server" CssClass="textarea" Text="BRailLabel" Width="64px"
Height="2px">DB Server: </brailaspcontrols:braillabel>

         Met Localization:

<brailaspcontrols:braillabel id="lblDBServer" runat="server" CssClass="textarea" key="lblDBServer" Text="BRailLabel"
Width="64px" Height="2px">DB Server: </brailaspcontrols:braillabel>

Het enige verschil is dat men een key="name” moet toevoegen. Dit moet gebeuren voor
elke component die men wil vertalen in meerdere talen.

Het XML bestand bevat de volgende structuur:

<?xml version="1.0" encoding="utf-8"?>
<elements>
<element name="lblDBServer" type="BRail.FrameWork.UI.WebControls.BRailLabel" form="Performance">
         <Text>
                   <nl>DB server: </nl>
                   <fr>DB server:</fr>
                   <en>DB server:</en>
                   <default>DB server:</default>
           </Text>
</element>
<element name="lblDBName" type="BRail.FrameWork.UI.WebControls.BRailLabel" form="Performance">
           <Text>
                   <nl>DB naam: </nl>
                   <fr>DB nom:</fr>
                   <en>DB name:</en>
                   <default>DB name:</default>
           </Text>
</element>
</elements>

De structuur is dat men eerst de naam van het object geeft, daarna het type van het object en
als laatste op welke pagina dit object staat.

Nu moet men enkel nog de klassen laten overerven van LocalizedPage zoals “public class
Performance : LocalizedPage”

In bijlage vindt u tevens het volledige document zodat u deze kunt inkijken.

Ik zal nu de code uitleggen die achter elk scherm zit en deze stap voor stap uitleggen.

Als eerste scherm zal ik Menu.aspx uitleggen. Dit scherm bevat de linken naar de andere
schermen en een taalkiezer. De HTML code achter het scherm is:
<%@       Register   TagPrefix="brailaspcontrols"              Namespace="BRail.FrameWork.UI.WebControls"
Assembly="BRail.FrameWork.AspControls,                          Version=1.0.0.1,           Culture=neutral,
PublicKeyToken=8ea659818aaae1aa" %>
                                                                                                       28

<%@          Page        language="c#"          Codebehind="Menu.aspx.cs"          AutoEventWireup="false"
Inherits="BRail.G153.Import.Gui.menu" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
         <HEAD>
                 <title>G153 Admin tool - menu</title>
                 <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
                 <meta name="CODE_LANGUAGE" Content="C#">
                 <meta name="vs_defaultClientScript" content="JavaScript">
                 <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
                 <link href="portal.css" rel="stylesheet" type="text/css">
         </HEAD>
         <body bgColor="#d3d3d3">
                 <form runat="server">
                           <a class="type1" href="Performance.aspx" target="main">Performance</a><BR>
                           <a class="type1" href="Serie.aspx" target="main">Serie</a><BR>
                           <a class="type1" href="Infos.aspx" target="main">Infos</a><BR>
                           <a class="type1" href="Period.aspx" target="main">Period</a><BR>
                           <BR>
                           <BRailAspControls:BRailDropDownList             id="LangSel"     runat="server"
AutoPostBack="True" CssClass="dropDownBox">
                                    <asp:ListItem Value="en-gb">English</asp:ListItem>
                                    <asp:ListItem Value="fr-be">Fran&#231;ais</asp:ListItem>
                                    <asp:ListItem Value="nl-be">Nederlands</asp:ListItem>
                           </BRailAspControls:BRailDropDownList></form>
         </body>
</HTML>

Op het scherm staan de vier linken naar de drie importschermen en naar het periodescherm.
Ook staat er een dropdown list met drie talen: Nederlands, Frans en Engels. Maar wat
gebeurd er als je een taal kiest. De gebeurtenis die zich voordoet is een
SelectedIndexChanged. Dit is gecodeerd in de Codebehind. De Codebehind is de
programmacode die zich achter de pagina bevindt zoals bij Visual Basic. Deze wordt altijd
op de server uitgevoerd en de Client krijgt enkel het resultaat te zien. Deze Codebehind
wordt in C# geprogrammeerd. In de Codebehind staat de volgende procedure die reageert
op de gebeurtenis SelectedIndexChanged van LangSel. Dit is de dropdown list.

private void LangSel_SelectedIndexChanged(object sender, System.EventArgs e)
          {
                   Session.Clear();
                   Session["language"]= LangSel.SelectedValue;
          }

Hier wordt eerst de Sessie leeggemaakt met “Session.Clear();”. Dit houdt in dat alle
sessievariabelen worden verwijderd. Wanneer een gebruiker naar een website gaat dan is dit
een sessie. Als er een andere gebruiker naar dezelfde webpagina gaat kijken dan is dit weer
een andere sessie. Een sessie is meestal beperkt in tijd en standaard staat dit op 20 minuten.
Dus iedere gebruiker heeft zijn eigen sessievariabelen zodat meerdere gebruikers de taal van
de applicatie kunnen kiezen en deze blijft dan gedurende de hele sessie geldig. Om een
sessievariabele aan te maken doet men Session[naam] = variabelen. In onze pagina halen we
de taal uit de dropdown list en steken deze in de sessievariabele language door
“Session["language"]= LangSel.SelectedValue;”. Als men nu naar een andere pagina gaat
dan kan men de sessievariabelen opvragen door “string strTaal = (string)
Session[“Language”];” te gebruiken.
                                                                                                                29

Nu zal ik de importschermen bespreken. De code achter de importschermen zijn identiek en
verschillen op sommige punten, daarom zal ik één importscherm uitleggen We zullen
beginnen met de HTML code te bespreken.

HTML
<%@          Page        language="c#"         AutoEventWireup="false"           CodeBehind="Performance.aspx.cs"
Inherits="BRail.G153.Import.Gui.Performance" %>

<%@         Register       TagPrefix="brailaspcontrols"          Namespace="BRail.FrameWork.UI.WebControls"
Assembly="BRail.FrameWork.AspControls, Version=1.0.0.1, Culture=neutral, PublicKeyToken=8ea659818aaae1aa" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

In dit gedeeldte wordt de Taal van het programmeren ingesteld die gebruikt wordt in de
Codebehind. Dit wordt gedaan door “Page language="c#" “. Ook wordt de naam van de
Codebehind ingesteld; hier is deze CodeBehind="Performance.aspx.cs". Omdat er gebruik
wordt gemaakt van BRail componenten die door de NMBS werden gemaakt moet men een
referentie     leggen     naar      deze    Namespace       met     “Namespace       =
"BRail.FrameWork.UI.WebControls"”. Door gebruik te maken van deze BRail
componenten kan men extra functionaliteit aan de componenten toevoegen zoals
bijvoorbeeld het ondersteunen van meerdere talen zonder heel complex te programmeren.
Exceptiemanagement doen zonder veel code toe te voegen of samengestelde componenten
gebruiken die geprogrammeerd zijn door collega’s.
<HTML>
<HEAD>
         <title>G153 Admin tool - Performance</title>
         <meta content="False" name="vs_snapToGrid">
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
         <meta content="C#" name="CODE_LANGUAGE">
         <meta content="JavaScript" name="vs_defaultClientScript">
<meta content=http://schemas.microsoft.com/intellisense/ie5 name="vs_targetSchema">
         <LINK href="portal.css" type="text/css" rel="stylesheet">

</HEAD>

Met <title>G153 Admin tool - Performance</title> wordt de title van de pagina ingesteld.
Met <LINK href="portal.css" type="text/css" rel="stylesheet"> wordt de cascading style
sheet die gebruikt wordt, ingesteld. De cascading style sheet die gebruikt wordt is portal.css.
Deze is een style sheet die standaard gebruikt wordt bij de NMBS.

Top of Form
<body bgColor="lightgrey">
         <form id="frmPerformance" method="post" runat="server">
         <table id="TABLE1" style="WIDTH: 720px; HEIGHT: 419px">
                   <TBODY>

Het formulier krijgt een ID zodat men kan refereren naar deze naam als men het formulier
wil aanspreken; dit wordt vooral in JavaScript gedaan. Ook wordt er gebruik gemaakt van
een tabel om alles te plaatsen op de pagina zodat men niet absoluut moet werken.

<tr>
<td style="WIDTH: 203px; HEIGHT: 26px" align="center" colSpan="2" vAlign="middle">

<brailaspcontrols:braillabel id="lblDBServer" runat="server" CssClass="textarea" key="lblDBServer" Text="BRailLabel"
Width="64px" Height="2px">DB Server: </brailaspcontrols:braillabel>
                                                                                                                 30

<brailaspcontrols:brailtextbox id="txtDBServer" runat="server" CssClass="textarea" key="txtDBServer" Width="120px"
RequiredErrorText ="*" RequiredField="True"></brailaspcontrols:brailtextbox>

</td>

<td style="WIDTH: 243px; HEIGHT: 32px" colSpan="2" vAlign="middle">

<brailaspcontrols:braillabel id="lblDBName" runat="server" CssClass="textarea" key="lblDBName" Text="BRailLabel"
Width="62px" Height="5px">DB Name:</brailaspcontrols:braillabel>

<brailaspcontrols:brailtextbox id="txtDBName" runat="server" CssClass="textarea" key="txtDBName" Width="120px"
RequiredErrorText ="*" RequiredField="True"></brailaspcontrols:brailtextbox>

</td>

<td style="WIDTH: 250px" colSpan="2" vAlign="middle">

<brailaspcontrols:braillabel   id="lblDate"         runat="server"          CssClass="textarea"        key="lblDate"
Text="BRailLabel"Height="2px">Date: </brailaspcontrols:braillabel>

<brailaspcontrols:braildatepicker       id="dtpDate"    runat="server"       CssClass="textarea"       key="dtpDate"
onLostfocus="ValidateForm()">
          <TitleStyle BackColor="#E0E0E0"></TitleStyle>
          <TodayDayStyle BackColor="#00C0C0"></TodayDayStyle>
          <DayHeaderStyle BackColor="#FFE0C0"></DayHeaderStyle>
          <DayStyle CssClass="textarea "></DayStyle>
          <CalendarStyle BackColor="#E0E0E0"></CalendarStyle>
          <SelectedDayStyle BackColor="Silver"></SelectedDayStyle>
</brailaspcontrols:braildatepicker>
<asp:requiredfieldvalidator         id="refDateReq"      runat="server"       key="refDateReq"          Width="8px"
ControlToValidate="dtpDate">*</asp:requiredfieldvalidator>

</td>
<TD rowSpan="3"></TD>
</tr>



Eerst word een nieuwe rij gemaakt in de tabel met <tr> en met <td> wordt er een nieuwe
kolom gemaakt. Hierin kan men componenten plaatsen zoals een label.

Dit doet men met de volgende code

“<brailaspcontrols:braillabel   id="lblDBServer"      runat="server"      CssClass="textarea"      key="lblDBServer"
Text="BRailLabel" Width="64px" Height="2px">DB Server: </brailaspcontrols:braillabel>”.


Een tekstbox maakt men op gelijke wijze als volgt

“<brailaspcontrols:brailtextbox id="txtDBName" runat="server" CssClass="textarea" key="txtDBName" Width="120px"
RequiredErrorText ="*" RequiredField="True"></brailaspcontrols:brailtextbox>”

Een heel handige component is de datepicker. Deze component laat u toe een datum te
selecteren uit een kalender. Deze kalender komt van de server waar de toepassing op draait.

Met de volgende code maakt men een dergelijke kalender:

<brailaspcontrols:braildatepicker    id="dtpDate"      runat="server"        CssClass="textarea"       key="dtpDate"
onLostfocus="ValidateForm()">
          <TitleStyle BackColor="#E0E0E0"></TitleStyle>
          <TodayDayStyle BackColor="#00C0C0"></TodayDayStyle>
          <DayHeaderStyle BackColor="#FFE0C0"></DayHeaderStyle>
          <DayStyle CssClass="textarea "></DayStyle>
          <CalendarStyle BackColor="#E0E0E0"></CalendarStyle>
                                                                                                                    31

          <SelectedDayStyle BackColor="Silver"></SelectedDayStyle>
</brailaspcontrols:braildatepicker>

Als men een controle op een veld wil doen dan kan men een validator toevoegen aan de
component. Deze validator controleert of het veld ingevuld is of niet. Indien het niet
ingevuld is dan geeft hij een melding die ook ondersteund wordt in drie talen.

Met deze code maakt men een validator:

<asp:requiredfieldvalidator    id="refDateReq"           runat="server"          key="refDateReq"          Width="8px"
ControlToValidate="dtpDate">*</asp:requiredfieldvalidator>

<TR>
<td style="WIDTH: 745px" align="center" colSpan="5" vAlign="middle">

<brailaspcontrols:braillabel id="lblPerformance"    runat="server"     CssClass="textarea"         key="lblPerformance"
Text="BRailLabel"
Width="113px" Height="2px">Performance root: </brailaspcontrols:braillabel>

<brailaspcontrols:brailtextbox id="txtRoot" runat="server"      CssClass="textarea"    key="txtRoot"    Width="408px"
RequiredErrorText="*"RequiredField="True">
</brailaspcontrols:brailtextbox>

<brailaspcontrols:brailbutton id="btnExplorer"   runat="server"     CssClass="textarea"       key="btnExplorer"
Text="OK"Width="32px" Height="21px" ImageUrl="icons/okIco.JPG"> </brailaspcontrols:brailbutton>

</td>
</TR>
<tr>
<td style="WIDTH: 204px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillabel id="lblDirectory" runat="server" CssClass="textarea" key="lblDirectory" Text="BRailLabel"
EnableViewState="False">Directory's</brailaspcontrols:braillabel>
</td>
<td style="WIDTH: 19px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1"></td>
<td style="WIDTH: 276px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillabel     id="lblFile"         runat="server"         CssClass="textarea"          key="lblFile"
Text="BRailLabel">Files</brailaspcontrols:braillabel>

</td>
<td style="WIDTH: 49px"></td>
<td style="WIDTH: 238px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillabel     id="lblSelect"        runat="server"       CssClass="textarea"         key="lblSelect"
Text="BRailLabel">Selected files</brailaspcontrols:braillabel>

</td>
</tr>

Een knop wordt gebruikt om een gebeurtenis te genereren zodat men iets kan programmeren
achter de gebeurtenis.

De volgende code maakt een knop op de webpagina:

<brailaspcontrols:brailbutton id="btnExplorer"   runat="server"     CssClass="textarea"       key="btnExplorer"
Text="OK"Width="32px" Height="21px" ImageUrl="icons/okIco.JPG"> </brailaspcontrols:brailbutton>

<tr>
<td style="WIDTH: 204px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillistbox id="lstDirectory" ondblclick="GotoDirectory();"    runat="server"    CssClass="textArea"
Width="174px" Height="272px"></brailaspcontrols:braillistbox>
                                                                                                                      32


</td>
<td style="WIDTH: 19px">

<asp:button id="btnInvGotoDir" runat="server" CssClass="textarea" Text="gtd" Width="18px"></asp:button>

</td>
<td style="WIDTH: 276px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillistbox id="lstFile" ondblclick="sel();" runat="server" CssClass="textArea" Width="180px"
Height="272px" SelectionMode="Multiple"></brailaspcontrols:braillistbox>

</td>
<td style="WIDTH: 49px">

<A onmousedown="sel()" href="#"><IMG height="20" alt='<%=ToolTipVariable%>' src="icons/forward.gif" width="20"
border="0"name="jsbSel"> </A>&nbsp;

</td>
<TD style="WIDTH: 238px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillistbox id="lstSelect" ondblclick="del(document.frmPerformance.lstSelect)" runat="server"
CssClass="textArea" Width="180px" Height="272px" EnableViewState="False" SelectionMode="Multiple">
</brailaspcontrols:braillistbox>

</TD>
<TD style="WIDTH: 271px; HEIGHT: 30px; TEXT-ALIGN: left" align="center" colSpan="1">

<A       onmousedown="del(document.frmPerformance.lstSelect)"       href="#"><IMG       id="btnDel"   height="20"
alt='<%=ToolTipVariable2%>' src="icons/button.delete_small.gif" width="20" border="0" name="jsbDel"></A>
&nbsp;
</TD>
</tr>
<tr>
<td align="center">

<brailaspcontrols:braillabel  id="lblDirClick"       runat="server"          CssClass="textarea"        key="lblDirClick"
Text="BRailLabel">Double click to open</brailaspcontrols:braillabel>

</td>
<td></td>
<td align="center">

<brailaspcontrols:braillabel  id="lblClickFiles"        runat="server"       CssClass="textarea"       key="lblClickFiles"
Text="BRailLabel">Double click to select and use shift to multiselect</brailaspcontrols:braillabel>
</td>
<td style="WIDTH: 49px"></td>
<td align="center">

<brailaspcontrols:braillabel id="lblClickSelect"    runat="server"          CssClass="textarea"       key="lblClickSelect"
Text="BRailLabel">Double click to remove</brailaspcontrols:braillabel>
</td>
</tr>
<tr>
<td style="WIDTH: 745px" align="center" colSpan="5">

<brailaspcontrols:brailbutton id="btnImport"     runat="server"   CssClass="textarea"    key="btnImport"    Text="Import
files"></brailaspcontrols:brailbutton>

</td>
</tr>
</TBODY>
</table>
                                                                                                                  33

Voor de navigatie en het selecteren van de bestanden zijn er listboxen voorzien die
dubbelklik gebeurtenissen hebben. Dit wil zeggen dat als men er op dubbelklikt er een
gebeurtenis ontstaat.

Om een listbox op het scherm te zetten is volgende code voldoende:

<brailaspcontrols:braillistbox id="lstDirectory" ondblclick="GotoDirectory();"   runat="server"   CssClass="textArea"
Width="174px" Height="272px"></brailaspcontrols:braillistbox>

Omdat sommige gebeurtenissen enkel aan de Client-side mogen afgehandeld worden heb ik
ook tekeningen gebruikt als een knop. Dus als de gebruiker klikt op de tekening dan
gedraagt deze tekening zich als een knop.

De volgende code zet een knop op het scherm:

<A onmousedown="sel()" href="#"><IMG height="20" alt='<%=ToolTipVariable%>' src="icons/forward.gif" width="20"
border="0"name="jsbSel"> </A>&nbsp;

<asp:validationsummary   id="ValidationSummary1"  runat="server"         key="ValidationSummary1"       Width="8px"
Height="58px" ShowMessageBox="True" ForeColor="LightGray">
</asp:validationsummary>

<asp:textbox id="txtInvisText" runat="server" Width="649px"></asp:textbox>
<brailaspcontrols:brailtextbox id="txtMessage" runat="server" key="txtMessage" Visible="False">
</brailaspcontrols:brailtextbox>

<asp:textbox id="txtInvisValue" runat="server" Width="649px"></asp:textbox>

<brailaspcontrols:BRailTextBox                id="txtBut1"                key="txtBut1"                runat="server"
Visible="False"></brailaspcontrols:BRailTextBox>
                  <brailaspcontrols:BRailTextBox               id="txtBut2"
key="txtBut2"                                               runat="server"
Visible="False"></brailaspcontrols:BRailTextBox></form>Bottom of Form

Om alle boodschappen te groeperen en een melding te geven van deze foutboodschap wordt
er gebruikt gemaakt van een validation summary. De validation summary vangt de
foutmeldingen op en geeft een message box aan de gebruiker.

Nu gaan we de Javascript bekijken.

<script language="javascript">

   function GotoDirectory()
         {
                  frmPerformance.btnInvGotoDir.click();
         }

Als men een javascript in de HTML wil zetten dan moet men openingstags gebruiken om
aan te geven dat we willen scripten. Deze beginnen met <script language="javascript"> en
eindigen op </script>

Soms moet men javascripts gebruiken omdat het anders niet mogelijk zou zijn. Daarom is
het nog een zeer belangrijke programmeertaal voor webtoepassingen.
Met het woord function maakt men een functie in javascript. Vb: function GotoDirectory().
Deze     functie    kan     iets   doen    zoals    op    een     knop    klikken    vb:
frmPerformance.btnInvGotoDir.click();. Deze bevat drie delen: het eerste deel is het
                                                                                                                         34

formulier waarop het object staat. Het tweede deel is het object en het derde deel is de
methode an het object.

function sel()
{

          for (var i = 0; i < document.frmPerformance.lstFile.length; i++)
          {
                     var ItemExists = false;

                     if (document.frmPerformance.lstFile.options[i].selected)
                     {
                        if (document.frmPerformance.lstSelect.length < 1)
                        {
                           document.frmPerformance.lstSelect.options [document.frmPerformance.lstSelect.length]
                 =new Option(document.frmPerformance.lstFile.options[i].text,
                                document.frmPerformance.lstFile.options[i].value );

                         }
                         else
                         {
                            for(var ii = 0; ii < document.frmPerformance.lstSelect.length; ii++)
                           {
                              if (document.frmPerformance.lstFile.options[i].value ==
                                   document.frmPerformance.lstSelect.options[ii].value)
                              {
                                   ItemExists = true;
                                   break;
                               }
                         }
                      if (!ItemExists)
                      {
                          document.frmPerformance.lstSelect.options[document.frmPerformance.lstSelect.length]
                         =                        new                 Option(document.frmPerformance.lstFile.options[i].text,
                         document.frmPerformance.lstFile.options[i].value );
                       }
                 }
          }
        }
       deltxt(document.frmPerformance.txtInvisText);
      deltxt(document.frmPerformance.txtInvisValue);
      backhold();
}

Deze functie wordt gebruikt om bestanden te selecteren en deze over te hevelen naar de
listbox met de geselecteerde bestanden. Eerst worden alle bestanden doorlopen die in de
listbox van de bestanden zitten. Dit wordt met ”for (var i = 0; i <
document.frmPerformance.lstFile.length; i++)” gedaan. Er wordt ook een variabele
aangemaakt met als standaardwaarde false. “var ItemExists = false;”. Daarna wordt er
gecontroleerd of er al een bestand zit in de listbox met geselecteerde bestanden. Dit gebeurd
als volgt “if (document.frmPerformance.lstSelect.length < 1)” Indien er geen inzitten, wordt
het    geselecteerde     bestand     onmiddellijk     toegevoegd.      Dit    gebeurd     met
“document.frmPerformance.lstSelect.options                        [document.frmPerformance.
lstSelect.length]=new               Option(document.frmPerformance.lstFile.options[i].text,
document.frmPerformance.lstFile.options[i].value ); “

Als er al bestanden in de listbox van geselecteerde bestanden zitten dan worden alle
bestanden die in de listbox van geselecteerde bestanden zitten, overlopen; dit gebeurd met: “
for(var ii = 0; ii < document.frmPerformance.lstSelect.length; ii++)”. In deze lus wordt dan
gecontroleerd of het bestand dat men wilt toevoegen reeds in de listbox zit van
geselecteerde bestanden. Dit gaat als volgt: if document.frmPerformance.lstFile.options
                                                                                             35

[i].value == document.frmPerformance.lstSelect.options[ii].value). Als een van deze
bestanden al in de listbox zit dan wordt de variabele op true gezet.” ItemExists = true;“en
wordt er uit de for lus gegaan met “break;” nu wordt er gecontroleerd of de variabele false is
dit wordt met “if (!ItemExists)“ als deze false is dan wordt het bestand toegevoegd in de
listbox                   met:                  “document.frmPerformance.lstSelect.options
[document.frmPerformance.lstSelect.length]=                    new                    Option
(document.frmPerformance.lstFile.options[i].text,
document.frmPerformance.lstFile.options[i].value );”

Dit algoritme wordt voor alle bestanden herhaald die in de listbox van de bestanden staan.

Er wordt nu een functie opgeroepen “deltxt(document.frmPerformance. txtInvisText);”.
Deze functie heeft als parameter een tekstveld. Deze tekstvelden zijn niet zichtbaar voor de
gebruiker. Een groot probleem voor webtoepassingen is de viewstate van de componenten.
Bijvoorbeeld: als de gebruiker in een tekstvak zijn naam intikt op de cliënt. De server weet
niet wat er in het tekstvak zit. Maar de gebruiker typt niet graag zijn naam in, waardoor de
programmeur zelf de waarden moest bijhouden. Nu in .Net is de programmeur verwend.
.Net houdt zelf de viewstate bij dus hoeft de programmeur deze waarde niet bij te houden.
Maar omdat de viewstate niet werkt voor listboxen moet de programmeur enkel voor
listboxen deze waarde zelf nog bijhouden. Deze viewstate is op de volgende manier
bijgehouden. Door twee tekstvakken toe te voegen en deze onzichtbaar te maken. In het
eerste tekstvak komen dan de namen van de bestanden te staan. Deze namen zijn ook
zichtbaar in de listbox. In het tweede tekstvak staat het volledige pad inclusief de
bestandsnaam. Dit is niet zichtbaar in de listbox maar word intern gebruikt bij het
aanspreken van de bestanden.

Ook wordt er een andere functie opgeroepen die “backhold();” noemt. Deze functie heeft
geen parameters.

Nu zullen we de twee functies bespreken.

We zullen beginnen met “deltxt(document.frmPerformance.txtInvisText);”.

function deltxt(indic)
{
  indic.value="";
}

Deze functie zet de value van de parameter om “”. Dus bevat deze geen waarde meer.

Nu gaan we de functie “backhold();” bespreken.

function backhold()
{
  for (var i = 0; i < document.frmPerformance.lstSelect.length; i++)
  {
    document.frmPerformance.txtInvisText.value +=
    document.frmPerformance.lstSelect.options[i].text + ";";

   document.frmPerformance.txtInvisValue.value +=
   document.frmPerformance.lstSelect.options[i].value + ";";
                                                                                       36

    }
}

Deze functie loopt door alle bestanden die geselecteerd zijn en bouwt de twee tekstvakken
terug op door telkens de waarde naar deze tekstvakken te kopiëren. Dit was de enige manier
om een werkend resultaat te bekomen. Bij elke toevoeging van een bestand worden de
tekstvakken helemaal terug leeggemaakt en terug opgebouwd. Dit lijkt omslachtig maar
gaat heel vlug omdat er geen tussenkomst van de server is.

De volgende functie wordt gebruikt om bestanden die geselecteerd waren in de listbox te
verwijderen uit de listbox.

function del(individuals)
{
  while (individuals.selectedIndex != -1)
    individuals.remove(individuals.selectedIndex);

        deltxt(document.frmPerformance.txtInvisText);
        deltxt(document.frmPerformance.txtInvisValue);
        backhold();
}

Deze functie krijgt als parameter een listbox mee. In ons voorbeeld
del(document.frmPerformance.lstSelect) de listbox van geselecteerde bestanden. Eerst
worden alle bestanden doorlopen die geselecteerd zijn. Dit gebeurd met            “while
(individuals.selectedIndex != -1) “. Alle bestanden worden verwijderd uit de listbox met
“individuals.remove(individuals.selectedIndex); “. Als alle bestanden verwijderd zijn,
worden de twee functies opgeroepen die we hierboven uitgelegd hebben namelijk “deltxt”
en “backhold”.

Op het laatste worden de twee tekstvakken en een knop die de gebruikers niet mogen zien
op onzichtbaar ingesteld met
frmPerformance.btnInvGotoDir.style.display              =           "none"            ;
frmPerformance.txtInvisText.style.display             =            "none"             ;
frmPerformance.txtInvisValue.style.display = "none" ;

De knop wordt gebruikt om een gebeurtenis te genereren die de listbox niet ondersteunt. De
gebruiker wou dat hij kon navigeren door de mappen als hij dubbelklikt op een map. Omdat
de listbox geen dubbelklik ondersteunt heb ik een knop gemaakt. Daar de code achter gezet
die nodig was en vervolgens “ondblclick=” een functie toegevoegd aan de HTML van de
listboxen. Hierdoor kon de gebruiker een dubbelklik gebruiken en werd er een gebeurtenis
gegenereerd.

Codebehind:

Het eerste wat men tegenkomt zijn de namespaces die worden gebruikt.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
                                                                                    37

using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
using BRail.FrameWork.ExceptionManagement.Common;
using BRail.FrameWork.ExceptionManagement.Interfaces;
using BRail.FrameWork.Localization;
using System.Globalization;

Een namespace is zeer belangrijk bij het programmeren. Bijvoorbeeld: als men de
namespace “using System.Web.UI.WebControls;” niet toevoegt dan kan men geen
webcontrols gebruiken.

namespace BRail.G153.Import.Gui
{

Dan maken we onze eigen namespace aan die volgens de standaard hetzelfde moet zijn als
het project.

public class Performance : LocalizedPage
{

Dan wordt er een nieuwe klasse gemaakt die dezelfde naam heeft als de webpagina. Deze
klasse geërfd van LocalizedPage. Dit zal in het deel van Localization duidelijk worden.

protected BRail.FrameWork.UI.WebControls.BRailTextBox txtDate;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblMessage;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblDBServer;
protected BRail.FrameWork.UI.WebControls.BRailTextBox txtDBServer;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblDBName;
protected BRail.FrameWork.UI.WebControls.BRailTextBox txtDBName;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblDate;
protected BRail.FrameWork.UI.WebControls.BRailDatePicker dtpDate;
protected System.Web.UI.WebControls.RequiredFieldValidator refDateReq;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblPerformance;
protected BRail.FrameWork.UI.WebControls.BRailTextBox txtRoot;
protected BRail.FrameWork.UI.WebControls.BRailButton btnExplorer;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblDirectory;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblFile;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblSelect;
protected BRail.FrameWork.UI.WebControls.BRailListBox lstDirectory;
protected System.Web.UI.WebControls.Button btnInvGotoDir;
protected BRail.FrameWork.UI.WebControls.BRailListBox lstFile;
protected BRail.FrameWork.UI.WebControls.BRailListBox lstSelect;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblDirClick;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblClickFiles;
protected BRail.FrameWork.UI.WebControls.BRailLabel lblClickSelect;
protected BRail.FrameWork.UI.WebControls.BRailButton btnImport;
protected System.Web.UI.WebControls.ValidationSummary ValidationSummary1;
protected System.Web.UI.WebControls.TextBox txtInvisText;
protected BRail.FrameWork.UI.WebControls.BRailTextBox txtMessage;
protected System.Web.UI.WebControls.TextBox txtInvisValue;
protected BRail.FrameWork.UI.WebControls.BRailTextBox txtBut1;
protected BRail.FrameWork.UI.WebControls.BRailTextBox txtBut2;

ArrayList myControls;
string lang;

Al de componenten die ook in HTML gedefinieerd zijn worden ook automatisch in de
Codebehind gedefinieerd. Ook worden hier twee variabellen gedefinieerd namelijk een
                                                                                                           38

ArrayList en een string. Deze zullen evenzeer in het deel over Localization uitgelegd
worden.

Zoals Windows toepassingen heeft, heeft nu ook webapplicaties methodes zoals een
Page_Load. We zullen deze code eens bekijken.

protected void Page_Load(object sender, System.EventArgs e)
{
           if ( Session["language"] != null )
          {
                      lang = (string)Session["language"];
          }
          else
          {
                      lang = "en-gb";
          }

         System.Threading.Thread.CurrentThread.CurrentUICulture=new CultureInfo(lang);

         btnImport.Attributes.Add("onclick","return confirm( '" + txtMessage.Text + "');");

         if (Application["Thread"] != null)
         {
                   CImportProxy _CImportProxy = (CImportProxy) Application["Thread"];

                  if (_CImportProxy.aThread.IsAlive)
                           Response.Redirect("Monitor.aspx",true);
                  else
                           Application["Thread"] = null;
         }

         if (! IsPostBack)
         {
                    LoadDBSettings();
                    GoToDir();
                    dtpDate.SelectedDate = System.DateTime.Now;

         }
         else
         {
                  try
                  {
                            ReloadList();
                  }

                  catch(System.SystemException ex)
                  {
                    BRailException newex = new BRailException("Attention there is someting wrong!", ex);

                  }
         }

}

De Page_Load wordt telkens uitgevoerd als de pagina geladen wordt. Dus ook als de pagina
vernieuwd wordt.

Eerst wordt er gecontroleerd of er een sessievariabele language bestaat. Als deze
sessievariabele bestaat dan wordt deze in een string lang geplaatst. Als er geen
sessievariabele is dan wordt “en-gb” in de string lang geplaatst.

Dan wordt de taal toegepast op de volledige pagina met de volgende code:
“System.Threading.Thread.CurrentThread.CurrentUICulture=new CultureInfo(lang);”
                                                                                        39


Daarna wordt er een attribuut toegevoegd aan een knop om een Messagebox te tonen met
een OK en Cancel knop op. Voordat men gaat importeren vraagt men de gebruiker of hij
zeker is dat hij deze bestanden wenst te importeren. Met de volgende code krijgt men een
MessageBox die dit doet.

btnImport.Attributes.Add("onclick","return confirm( '" + txtMessage.Text + "');");

Er worden twee parameters toegevoegd de eerste is de gebeurtenis wanneer de messagebox
tevoorschijn moet komen. De tweede parameter is de Messagebox zelf, met de tekst die uit
een tekstvak komt, die ook in meerdere talen beschikbaar is, maar onzichtbaar is voor de
gebruiker.
Daarna wordt er gecontroleerd of er een applicatievariabele “Thread” bestaat. Indien de
applicatievariabele bestaat dan wordt er deze code uitgevoerd “CImportProxy
_CImportProxy = (CImportProxy) Application["Thread"];”. Er wordt een instantie van de
klasse CImportProxy gemaakt die de inhoud van de applicatievariabele als waarde krijgt.
Daarna wordt ook gecontroleerd of de aThread nog Alive is. Indien de thread, alive is, dan
gaat men naar het monitorscherm. Een import maakt een nieuwe thread. Als deze nog
bestaat dan mag men geen nieuwe thread maken omdat anders de databaseserver niet zou
kunnen volgen. Daarom krijgt de gebruiker, nadat hij het importproces gestart heeft enkel
het monitorscherm te zien en geen importscherm meer.
Als er geen applicatievariabele “Thread” bestaat dan wordt deze op nul gezet met volgende
code: “Application["Thread"] = null;”.

Nu wordt er gecontroleerd of er een postback is gebeurd of niet. Een postback is een
vernieuwing van het scherm. De eerste keer dat een pagina geladen is, is dit geen postback.
Als men op een knop klikt en de pagina wordt herladen, dan is dit wel een postback.

Als er geen postback gebeurd is dan worden twee procedures aangeroepen en het datumveld
wordt gelijkgesteld met de dag van vandaag. Dit gebeurd als volgt:
        LoadDBSettings();
        GoToDir();
        dtpDate.SelectedDate = System.DateTime.Now;

De twee procedures zullen later uitgelegd worden.

Als er een postback is gebeurd, dan wordt er een andere procedure aangeroepen:
ReloadList();. Deze zal ook later uitgelegd worden.

private void LoadDBSettings()
{
          try
          {
                  // create reader & open file
                  StreamReader tr = File.OpenText(Server.MapPath("DBSettings.txt"));

                  // read line of text
                  txtDBServer.Text=(tr.ReadLine());
                  txtDBName.Text=(tr.ReadLine());
                  txtRoot.Text = (tr.ReadLine());

                  // close the stream
                  tr.Close();
         }
         catch(System.IO.FileNotFoundException ex)
                                                                                                               40

         {
                   BRailException newex = new BRailException("The file does not exsists!", ex);

                   txtRoot.Text = Server.MapPath("\\");
                   GoToDir();
         }
         catch( System.UnauthorizedAccessException ex)
         {
                   BRailException newex = new BRailException("You don't have access to the directory!", ex);
         }
}

Deze procedure leest gegevens uit een bestand, zet deze op het scherm zodat de gebruiker
niet telkens de server en de naam van de database moet invullen. Eerst wordt het bestand
geopend en een Streamreader aangemaakt zodat men het bestand kan lezen. Dit is de code:
“tr = File.OpenText(Server.MapPath("DBSettings.txt")); “. Dan wordt de server, de naam
en de root uit het bestand ingelezen en vervolgens in de overeenkomstige tekstvelden
geplaatst. Dit wordt als volgt gedaan: txtDBServer.Text =(tr.ReadLine());
txtDBName.Text=(tr.ReadLine()); txtRoot.Text = (tr.ReadLine());”
Daarna wordt het bestand gesloten met “tr.Close();”. Er worden ook twee excepties
opgevangen: als het bestand niet bestaat en als men geen toegang heeft tot de map.
public void GoToDir()
{
          try
          {
                  string strRoot = txtRoot.Text;
                  DirectoryInfo dir = new DirectoryInfo (strRoot) ;
                  DirectoryInfo[] Map = dir.GetDirectories() ;

                   FileInfo[] list1 = dir.GetFiles ("presthld.*");
                   FileInfo[] list2 = dir.GetFiles ("prestchg.*");
                   FileInfo[] list3 = dir.GetFiles ("prestelc.*");

                   lstFile.Items.Clear() ;
                   lstDirectory.Items.Clear() ;

                   string strRootList = Server.MapPath("\\");
                   lstDirectory.Items.Add(new ListItem("<ROOT>", strRootList));

                   lstDirectory.Items.Add(new ListItem(".."));

                   foreach (FileInfo fi in list1)
                   {

                             string day = "";
                             string month = "";
                             if (fi.CreationTime.Day < 10)
                             {
                                        day = "0" + fi.CreationTime.Day;
                             }
                             else
                             {
                                        day = "" + fi.CreationTime.Day;
                             }

                             if (fi.CreationTime.Month < 10)
                             {
                                        month = "0" + fi.CreationTime.Month;
                             }
                             else
                             {
                                        month = "" + fi.CreationTime.Month;
                             }
                                                                                                            41

                   string lijn = "[ " + day + "/" + month + "/" + fi.CreationTime.Year + " ] " + fi.Name;
                   lstFile.Items.Add (new ListItem (lijn, fi.FullName)) ;

         }
         foreach (FileInfo fi in list2)
         {
                   string day = "";
                   string month = "";
                   if (fi.CreationTime.Day < 10)
                   {
                              day = "0" + fi.CreationTime.Day;
                   }
                   else
                   {
                              day = "" + fi.CreationTime.Day;
                   }
                   if (fi.CreationTime.Month < 10)
                   {
                              month = "0" + fi.CreationTime.Month;
                   }
                   else
                   {
                              month = "" + fi.CreationTime.Month;
                   }

                   string lijn = "[ " + day + "/" + month + "/" + fi.CreationTime.Year + " ] " + fi.Name;
                   lstFile.Items.Add (new ListItem (lijn, fi.FullName)) ;

         }

         foreach (FileInfo fi in list3)
         {
                   string day = "";
                   string month = "";
                   if (fi.CreationTime.Day < 10)
                   {
                              day = "0" + fi.CreationTime.Day;
                   }
                   else
                   {
                              day = ""+fi.CreationTime.Day;
                   }
                   if (fi.CreationTime.Month < 10)
                   {
                              month = "0" + fi.CreationTime.Month;
                   }
                   else
                   {
                              month = "" + fi.CreationTime.Month;
                   }

                   string lijn = "[ " + day + "/" + month + "/" + fi.CreationTime.Year + " ] " + fi.Name;
                   lstFile.Items.Add (new ListItem (lijn, fi.FullName)) ;

         }
         foreach (DirectoryInfo di in Map)
         {
                   lstDirectory.Items.Add (new ListItem (di.Name,di.Name)) ;
         }

}
catch(System.IO.DirectoryNotFoundException ex)
{
         BRailException newex = new BRailException("The directory does not exsists", ex);

         lstFile.Items.Clear();
         lstDirectory.Items.Clear();
}
                                                                                                                 42

          catch(System.ArgumentOutOfRangeException ex)
          {
                   BRailException newex = new BRailException("Argument is out of range", ex);
          }
          catch(System.ArgumentException ex)
          {
                   BRailException newex = new BRailException("There are illegal characters in the root!", ex);

                    lstFile.Items.Clear();
                    lstDirectory.Items.Clear();
          }
          catch( System.UnauthorizedAccessException ex)
          {
                    BRailException newex = new BRailException("You don't have access to the directory", ex);


          }
          catch(System.IO.IOException ex)
          {
                   BRailException newex = new BRailException("The diskdrive is not ready", ex);

                    lstFile.Items.Clear();
                    lstDirectory.Items.Clear();
          }
}

Deze procedure haalt de mappen en de bestanden op die onder de root staan en zet deze in
de twee listboxen. De root wordt uit een tekstvak ingelezen. Eerst wordt de waarde van de
root in een stringvariabele ingelezen. Zoals “string strRoot = txtRoot.Text;”. Daarna word er
een variabele gemaakt van het type directoryinfo. Deze krijgt als parameter de root mee die
de gebruiker gekozen heeft. “DirectoryInfo dir = new DirectoryInfo (strRoot) ;”. Nu kan
men heel gemakkelijk alle mappen en bestanden ophalen die in deze root zitten. Met de
volgende code worden de mappen opgehaald uit de root. “DirectoryInfo[] Map =
dir.GetDirectories() ;”.

Om de bestanden op te halen heeft men ook een speciale variabele nodig die FileInfo heet.
Omdat er enkel speciale bestanden mogen geselecteerd worden moet er gefilterd worden.
Dit kan men tijdens het ophalen van de bestanden. Als men een GetFile doet dan kan men
als parameter het bestandtype meegeven zodat enkel deze bestanden getoond worden. Vb:
FileInfo[] list1 = dir.GetFiles ("presthld.*");. Dit wordt gedaan voor alle typen van
bestanden die getoond mogen worden. Ook worden de listboxen van de mappen en
bestanden leeg gemaakt met de Clear methode.

Er worden twee speciale items toegevoegd aan de listbox van de mappen. Namelijk de items
“<ROOT>” en “..”. Als de gebruiker klikt op “<ROOT>” dan gaat hij naar de root van de
toepassing op de server. Indien hij op “..” klikt dan gaat hij één stap hoger in de
mappenstructuur.

Omdat de gebruiker wil dat er in de listbox van bestanden ook de datum van aanmaak bij de
bestandsnaam komt te staan, zodat de gebruiker weet wanneer deze bestanden aangemaakt
zijn, wordt er voor elke type van bestanden een lus gemaakt die telkens de datum toevoegt
aan de bestandsnaam. Op het laatste worden ook de mappen toegevoegd aan de listbox van
de mappen. Dit wordt ook met een lus gedaan. Hier worden ook verschillende excepties
opgevangen die voorkomen dat er een foutboodschap op het scherm van de gebruiker komt.
private void ReloadList()
{
          lstSelect.Items.Clear();
                                                                                                                  43

         if (txtInvisText.Text != "")
         {
                    string lineText = txtInvisText.Text;
                    string lineValue = txtInvisValue.Text;

                   string [] SplittedText = lineText.Split(';');
                   string [] SplittedValues = lineValue.Split(';');

                   for (int i =0; i < SplittedText.Length; i++)
                               if (SplittedText[i] != "")
                                          lstSelect.Items.Add(new ListItem(SplittedText[i],SplittedValues[i]));
         }
}

Deze procedure houdt eigenlijk de viewstate van de listbox met geselecteerde bestanden bij.
Bij elke vernieuwing van het scherm wordt de waarde van de listbox bijgehouden in twee
tekstvakken. Dus moet er na elke vernieuwing, deze waarden terug in de listbox van
geselecteerde bestanden toegevoegd worden. Eerst word de waarde van de twee tekstvakken
opgehaald. Dan worden twee Arrays van strings gemaakt die de waarde van elk bestand
splitst per bestand. Daarna worden deze waarden toegevoegd in de listbox met een lus.
protected void Page_UnLoad(object sender, System.EventArgs e)
{
         SaveDBSettings();
}

Deze procedure wordt telkens uitgevoerd als de pagina gesloten wordt. Hier wordt de
procedure SaveDBSettings uitgevoerd.
private void SaveDBSettings()
{
          try
          {
                  FileStream fs;
                  StreamWriter sw;

                  fs = new FileStream(Server.MapPath("DBSettings.txt"), FileMode.OpenOrCreate,
         FileAccess.Write);

                   sw = new StreamWriter(fs);

                   string strDBServer = txtDBServer.Text;
                   string strDBName = txtDBName.Text;
                   string strRoot = txtRoot.Text;

                   //Write the field name information to the file.
                   sw.WriteLine(strDBServer);
                   sw.WriteLine(strDBName);
                   sw.WriteLine(strRoot);


                   //Reinitialize the string for data.
                   strDBServer = "";
                   strDBName ="";
                   strRoot = "";

                   sw.Close();
                   fs.Close();
         }
         catch(System.IO.IOException ex)
         {
                  BRailException newex = new BRailException("Attention there is someting wrong!", ex);
         }
}
                                                                                                              44


In deze procedure worden de waarden van tekstvakken bewaard in een bestand zodat de
gebruiker bij een volgend bezoek direct kan verder werken en niet eerst de server en
database moet intypen. Ook omdat deze waarden vast zijn en dat de bestanden altijd in
dezelfde database geïmporteerd worden.
public void GoToFile()
{
          int nr = lstSelect.Items.Count;
          string [] listcontent = new string[lstSelect.Items.Count];
          string [] listvalue = new string[lstSelect.Items.Count];

          try
          {
                    if (lstSelect.Items.Count !=0)
                    {
                               for (int i = 0; i < lstSelect.Items.Count;i++)
                               {
                                           listcontent[i] = lstSelect.Items[i].Text;
                                           listvalue[i] = lstSelect.Items[i].Value;
                               }
                    }
                    if (lstDirectory.SelectedItem.Text =="..")
                    {
                               string strNieuweRoot = txtRoot.Text;
                               string strVb = strNieuweRoot.Substring(0,(strNieuweRoot.LastIndexOf("\\")));
                               string strRoot = strVb.Substring(0,strVb.LastIndexOf("\\"));

                              txtRoot.Text = strRoot;
                              txtRoot.Text = txtRoot.Text + "\\";


                               GoToDir();
                    }
                    if (lstDirectory.SelectedItem.Text == "<ROOT>")
                    {
                               txtRoot.Text = lstDirectory.SelectedItem.Value;

                              string strRoot = txtRoot.Text;

                              GoToDir();
                    }
                    else
                    {
                              GoToDir();

          }
          catch(System.NullReferenceException ex)
          {
                    BRailException newex = new BRailException("Please select a directory", ex);
          }
          catch( System.UnauthorizedAccessException ex)
          {
                    BRailException newex = new BRailException("You don't have access to the
          directory", ex);
                    txtRoot.Text = Server.MapPath("\\");
          }
          catch(System.IO.DirectoryNotFoundException ex)
          {
                    BRailException newex = new BRailException("The directory does not exsists", ex);
          }
          catch(System.ArgumentOutOfRangeException ex)
          {
                    BRailException newex = new BRailException("Argument is out of range", ex);
          }
}
                                                                                                    45


In deze procedure wordt gecontroleerd of er geklikt is op één van de speciale items “..” of
“<ROOT>”. Als dit het geval is, wordt er een nieuwe root gemaakt en bewaard in een
roottekstvak. Daarna word de procedure GoToDir opgeroepen die hiervoor uitgelegd werd.

private void StartAndControl()
{
         if (lstSelect.Items.Count > 0)
         {
                   string[,] strFiles = new string[2,lstSelect.Items.Count];
                   for (int i = 0; i < lstSelect.Items.Count; i++)
                   {

                             string bestName = lstSelect.Items[i].Value;
                             strFiles[0, i] = bestName.Substring(bestName.LastIndexOf("\\") + 1);
                             strFiles[1, i] = lstSelect.Items[i].Value;
                   }

                 //0 = Performance
                 Application["Thread"]=new CImportProxy(strFiles,
dtpDate.SelectedDate,txtDBServer.Text, txtDBName.Text,0 );

                   Response.Redirect("Monitor.aspx");
         }

}

Deze procedure start het importproces. Eerst wordt er een Array opgevuld met de
bestandsnamen en bestandspaden. Dan wordt er een applicatievariabele gemaakt van het
type CImportProxy met verschillende parameters. Deze klasse zal later uitgelegd worden.
De gebruiker wordt herleid naar het monitor scherm.
private void btnInvGotoDir_Click(object sender, System.EventArgs e)
{
          GoToFile();
}

Deze procedure wordt gebruikt als men op de knop btnInvGotoDir klikt. Deze is niet
zichtbaar voor de gebruiker maar is nodig zodat de gebruiker kan dubbelklikken op de
listbox.
private void btnExplorer_Click(object sender, System.EventArgs e)
{

         GoToDir();
         SaveDBSettings();
         LoadDBSettings();
}

Deze procedure wordt aangeroepen als men op de OK knop klikt. Dan worden de volgende
procedures aangeroepen omdat de gebruiker manueel een andere root kan intypen en dan op
de OK knop klikken. Daarom wordt eerst GoToDir aangeroepen. Dan worden de velden
bewaard in het bestand en terug opgehaald.
private void btnImport_Click(object sender, System.EventArgs e)
{
          StartAndControl();
}
                                                                                                               46

Deze procedure wordt opgestart als men op de knop Import klikt. Dan wordt de procedure
StartAndControl opgestart.
protected string ToolTipVariable
{
          get
          {
                   return txtBut1.Text;
          }
}

protected string ToolTipVariable2
{
          get
          {
                   return txtBut2.Text ;
          }
}

Deze twee procedures worden uitgevoerd telkens de pagina wordt geladen. Het zijn speciale
procedures. Omdat men ook HTML componenten in verschillende talen wil aanbieden kan
men gebruik maken van Pageproperty’s. Deze procedure geeft enkel een waarde terug met
de methode get. Voorbeeld: <A onmousedown="sel()" href="#"><IMG height="20"
alt='<%=ToolTipVariable%>'                 src="icons/forward.gif"             width="20"
border="0"name="jsbSel"> </A> Dit is een knop die een tooltip krijgt in meerdere talen. De
tooltip in deze component heet alt. Door deze in te stellen met ‘<%=ToolTipVariable%>’, is
ze in meerdere talen beschikbaar. Op het scherm maakt men een tekstvak die dan via
localizatin de taal krijgt die door de gebruiker gebruikt wordt. De procedure “protected
string ToolTipVariable” geeft dan de waarde van dit tekstvak terug aan de HTML zodat in
plaats van ‘<%=ToolTipVariable%>’, een boodschap die in meerdere talen beschikbaar is.

Deze code is voor alle importschermen hetzelfde. Nu zal het Period scherm uitgelegd
worden.

Het scherm periode dient om een preview te geven van periodebestanden. Enkel de interface
is af maar de procedure om deze bestanden in te kijken is nog niet af omdat dit geen
prioriteit voor het project vormde. Daarom dat de programmeur die deze procedures moest
programmeren er nog niet aan begonnen is. Omdat de code en de procedures hetzelfde zijn
als deze van de importschermen zal ik deze niet verder uitleggen.
<%@              Page           language="c#"            Codebehind="Period.aspx.cs"        AutoEventWireup="false"
Inherits="BRail.G153.Import.Gui.Period" %>
<%@             Register          TagPrefix="brailaspcontrols"        Namespace="BRail.FrameWork.UI.WebControls"
Assembly="BRail.FrameWork.AspControls, Version=1.0.0.1, Culture=neutral, PublicKeyToken=8ea659818aaae1aa" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
          <title>G153 Admin tool - Periode</title>
          <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
          <meta name="CODE_LANGUAGE" Content="C#">
          <meta name="vs_defaultClientScript" content="JavaScript">
          <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
          <link href="portal.css" rel="stylesheet" type="text/css">
</HEAD>
<body bgColor="lightgrey">
          <form id="frmPeriod" method="post" runat="server">
          <script language="javascript">

         function GotoDirectory()
         {
                                                                                                        47

          frmPeriod.btnInvGotoDir.click();
}
</script>
<table id="TABLE1">
<TR>
<td align="center" colSpan="5" style="HEIGHT: 25px">

<brailaspcontrols:braillabel id="lblPeriod"    runat="server"      Height="2px"      Width="113px"     Text
="BRailLabel" key="lblPeriod" CssClass="textarea"> Period root: </brailaspcontrols:braillabel>

<brailaspcontrols:brailtextbox   id="txtRoot"     key="txtRoot"        runat="server"       Width="408px"
RequiredField="True" RequiredErrorText="*"CssClass="textarea"> </brailaspcontrols:brailtextbox>
<brailaspcontrols:brailbutton  key="btnExplorer"   id="btnExplorer"      runat="server"      Height="22px"
Width="32px" Text="OK"CssClass="textarea"></brailaspcontrols:brailbutton></td>
</TR>
<tr>
<td style="WIDTH: 204px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillabel id="lblDirectory" runat="server" Text="BRailLabel"   key="lblDirectory"
CssClass="textarea">Directory's</brailaspcontrols:braillabel>
</td>
<td style="WIDTH: 19px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1"></td>
<td style="WIDTH: 179px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillabel     id="lblFile"       runat="server"    Text="BRailLabel"        key="lblFile"
CssClass="textarea">Files</brailaspcontrols:braillabel>

</td>
<td style="WIDTH: 12px"></td>
<td style="WIDTH: 271px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1"></td>
</tr>
<tr>
<td style="WIDTH: 204px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillistbox id="lstDirectory"      ondblclick="GotoDirectory();"           runat="server"
Height="272px" Width="174px"CssClass="textarea"></brailaspcontrols:braillistbox>

</td>
<td style="WIDTH: 19px">
<asp:button         id="btnInvGotoDir"      runat="server"         Width="18px"                  Text="gtd"
CssClass="textarea"></asp:button>
</td>
<td style="WIDTH: 179px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillistbox   id="lstFile"        runat="server"   Height="272px"         Width="180px"
CssClass="textarea"></brailaspcontrols:braillistbox>

</td>
<td style="WIDTH: 12px"><A href="#"></A>&nbsp;<A href="#"> </A>
</td>
<td style="WIDTH: 271px; HEIGHT: 30px; TEXT-ALIGN: center" align="center" colSpan="1">

<brailaspcontrols:braillistbox id="lstPreview"    runat="server"     Height="272px"       Width="260px"
SelectionMode="Multiple" EnableViewState="False" CssClass="textarea">   </brailaspcontrols:braillistbox>

</td>
<td style="WIDTH: 271px; HEIGHT: 30px; TEXT-ALIGN: center" align="center"           colSpan="1">&nbsp;
</td>
<tr>
<td align="center">

<brailaspcontrols:BRailLabel key="lblDirClick" id="lblDirClick" runat="server"            Text="BRailLabel"
CssClass="textarea">Double click to open</brailaspcontrols:BRailLabel>

</td>
<td></td>
<td align="center" style="WIDTH: 179px">
                                                                                                              48

         <brailaspcontrols:BRailLabel key="lblClickFiles" id="lblClickFiles" runat="server" Text="BRailLabel"
         CssClass="textarea">Double click to select and use shift to multiselect</brailaspcontrols:BRailLabel>

         </td>
         <td></td>
         <td align="center">

         <brailaspcontrols:BRailButton key="btnImport" id="btnImport"      runat="server"   Text="Preview   files"
         CssClass="textarea"></brailaspcontrols:BRailButton>
         </td>
         </tr>
         </table>

         <asp:validationsummary     id="ValidationSummary1"      key="ValidationSummary1"    runat="server"
         Height="58px" Width="8px" ForeColor="LightGray"                            ShowMessageBox="True"
         HeaderText="Foutboodschap"></asp:validationsummary></form>

       <script language="javascript">
                 frmPeriod.btnInvGotoDir.style.display = "none" ;
       </script>
       </body>
</HTML>


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
using BRail.FrameWork.ExceptionManagement.Interfaces;
using BRail.FrameWork.ExceptionManagement.Common;
using BRail.FrameWork.Localization;
using System.Globalization;


namespace BRail.G153.Import.Gui
{
        /// <summary>
        /// Summary description for Periode.
        /// </summary>
        public class Period : LocalizedPage
        {
                  protected System.Web.UI.WebControls.Button btnOverhevelen;
                  protected System.Web.UI.WebControls.ValidationSummary ValidationSummary1;
                  protected BRail.FrameWork.UI.WebControls.BRailListBox lstDirectory;
                  protected BRail.FrameWork.UI.WebControls.BRailListBox lstFile;
                  protected BRail.FrameWork.UI.WebControls.BRailButton btnExplorer;
                  protected BRail.FrameWork.UI.WebControls.BRailLabel lblDirectory;
                  protected BRail.FrameWork.UI.WebControls.BRailLabel lblFile;
                  protected System.Web.UI.WebControls.Button btnInvGotoDir;
                  protected BRail.FrameWork.UI.WebControls.BRailListBox lstPreview;
                  protected BRail.FrameWork.UI.WebControls.BRailTextBox txtRoot;
                  protected BRail.FrameWork.UI.WebControls.BRailLabel lblPeriod;

                  protected BRail.FrameWork.UI.WebControls.BRailLabel lblDirClick;
                  protected BRail.FrameWork.UI.WebControls.BRailLabel lblClickFiles;
                  protected BRail.FrameWork.UI.WebControls.BRailButton btnImport;

                  string lang;
                  ArrayList myControls;
                                                                                           49


protected void Page_Load(object sender, System.EventArgs e)
{
          if ( Session["language"] != null )
          {
                     lang = (string)Session["language"];

         }
         else
         {
                     lang = "en-gb";

         }

         System.Threading.Thread.CurrentThread.CurrentUICulture=new CultureInfo(lang);

         if (! IsPostBack)
         {
                    txtRoot.Text = Server.MapPath("\\");

                     GoToDir();
         }

}




public void GoToFile()
{
          try
          {
            if (lstDirectory.SelectedItem.Text =="..")
          {
                     string strNieuweRoot = txtRoot.Text;

                     string strVb = strNieuweRoot.Substring(0,(strNieuweRoot.LastIndexOf
         ("\\")));

                     string strRoot = strVb.Substring(0,strVb.LastIndexOf("\\"));

                     txtRoot.Text = strRoot;
                     txtRoot.Text = txtRoot.Text + "\\";
                     GoToDir();

         }
         if (lstDirectory.SelectedItem.Text == "<ROOT>")
         {
                    txtRoot.Text = lstDirectory.SelectedItem.Value;
                    string strRoot = txtRoot.Text;

                     GoToDir();

         }
         else
         {

                     string strRoot = txtRoot.Text;

                     strRoot = strRoot + lstDirectory.SelectedItem.Value;

                     strRoot = strRoot + "\\";

                     txtRoot.Text = strRoot;

                     DirectoryInfo dir = new DirectoryInfo (strRoot) ;

                     DirectoryInfo[] Map = dir.GetDirectories() ;
                                                                                                 50


                       FileInfo[] list1 = dir.GetFiles ();

                       lstFile.Items.Clear() ;
                       lstDirectory.Items.Clear() ;

                       string strRootList = Server.MapPath("\\");
                       lstDirectory.Items.Add(new ListItem("<ROOT>", strRootList));

                       lstDirectory.Items.Add(new ListItem(".."));

                       foreach (FileInfo fi in list1)
                       {
                                 string day = "";
                                 string month = "";

                                 if (fi.CreationTime.Day < 10)
                                 {
                                            day = "0" + fi.CreationTime.Day;
                                 }
                                 else
                                 {
                                            day = "" + fi.CreationTime.Day;
                                 }
                                 if (fi.CreationTime.Month < 10)
                                 {
                                            month = "0" + fi.CreationTime.Month;
                                 }
                                 else
                                 {
                                            month = "" +fi.CreationTime.Month;
                                 }

                                 string lijn = "[ " + day + "/" + month + "/" +
                       fi.CreationTime.Year + " ] " + fi.Name;
                                 lstFile.Items.Add (new ListItem (lijn, fi.FullName)) ;

                       }

                       foreach (DirectoryInfo di in Map)
                       {
                                 lstDirectory.Items.Add (new ListItem (di.Name,di.Name)) ;
                       }
             }

    }
    catch(System.NullReferenceException ex)
    {
             BRailException newex = new BRailException("Please select a directory", ex);

    }
    catch( System.UnauthorizedAccessException ex)
    {
              BRailException newex = new BRailException("You don't have access to the
    directory", ex);
              txtRoot.Text = Server.MapPath("\\");
    }
    catch(System.IO.DirectoryNotFoundException ex)
    {
              BRailException newex = new BRailException("The directory does not exsists", ex);


    }
    catch(System.ArgumentOutOfRangeException ex)
    {
             BRailException newex = new BRailException("The argument is out of range", ex);
}
}
                                                                                                              51


public void GoToDir()
{
          try
          {
                  string strRoot = txtRoot.Text;

                   DirectoryInfo dir = new DirectoryInfo (strRoot) ;

                   DirectoryInfo[] Map = dir.GetDirectories() ;

                   FileInfo[] list1 = dir.GetFiles ();

                   lstFile.Items.Clear() ;
                   lstDirectory.Items.Clear() ;

                   string strRootList = Server.MapPath("\\");
                   lstDirectory.Items.Add(new ListItem("<ROOT>", strRootList));

                   lstDirectory.Items.Add(new ListItem(".."));

                   foreach (FileInfo fi in list1)
                   {

                              string day = "";
                              string month = "";

                              if (fi.CreationTime.Day < 10)
                              {
                                         day = "0" + fi.CreationTime.Day;
                              }
                              else
                              {
                                         day = "" + fi.CreationTime.Day;
                              }
                              if (fi.CreationTime.Month < 10)
                              {
                                         month = "0" + fi.CreationTime.Month;
                              }
                              else
                              {
                                         month = "" + fi.CreationTime.Month;
                              }

                              string lijn = "[ " + day + "/" + month + "/" + fi.CreationTime.Year + " ] " +
                   fi.Name;
                              lstFile.Items.Add (new ListItem (lijn, fi.FullName)) ;

                   }


                   foreach (DirectoryInfo di in Map)
                   {
                             lstDirectory.Items.Add (new ListItem (di.Name,di.Name)) ;
                   }

         }
         catch(System.IO.DirectoryNotFoundException ex)
         {
                  BRailException newex = new BRailException("The file is not found", ex);

                   lstFile.Items.Clear();
                   lstDirectory.Items.Clear();
         }
         catch(System.ArgumentOutOfRangeException ex)
         {
                  BRailException newex = new BRailException("Attention there is a problem", ex);
         }
                                                                                                                52

                  catch(System.ArgumentException ex)
                  {
                             BRailException newex = new BRailException("there are illegal characters in the
                  root", ex);

                            lstFile.Items.Clear();
                            lstDirectory.Items.Clear();
                  }
                  catch( System.UnauthorizedAccessException ex)
                  {
                            BRailException newex = new BRailException("You don't have access to the
                  directory", ex);

                  }
                  catch(System.IO.IOException ex)
                  {
                           BRailException newex = new BRailException("The diskdrive is not ready", ex);

                            lstFile.Items.Clear();
                            lstDirectory.Items.Clear();
                  }


         }

         private void btnGotoDir_Click(object sender, System.Web.UI.ImageClickEventArgs e)
         {
                   GoToFile();
         }

         private void btnInvGotoDir_Click(object sender, System.EventArgs e)
         {
                   GoToFile();
         }

         private void btnExplorer_Click(object sender, System.EventArgs e)
         {
                   GoToDir();
         }
}


Op het monitorscherm staat een titel, een groot tekstvak, een knop om het proces te stoppen
en een checkbox om het vernieuwen van het scherm te stoppen.
<%@            Register          TagPrefix="brailaspcontrols"            Namespace="BRail.FrameWork.UI.WebControls"
Assembly="BRail.FrameWork.AspControls, Version=1.0.0.1, Culture=neutral, PublicKeyToken=8ea659818aaae1aa" %>
<%@            Page           language="c#"            Codebehind="Monitor.aspx.cs"          AutoEventWireup="false"
Inherits="BRail.G153.Import.Gui.Monitor" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
          <HEAD>
                   <title>G153 Admin tool - Monitor</title>
                   <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
                   <meta name="CODE_LANGUAGE" Content="C#">
                   <meta name="vs_defaultClientScript" content="JavaScript">
                   <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
                   <link href="portal.css" rel="stylesheet" type="text/css">
          </HEAD>
          <body bgColor="buttonface">
          <form id="Form1" method="post" runat="server">
          <TABLE id="Table1" cellSpacing="1" cellPadding="1" border="1">
          <TR>
          <TD style="HEIGHT: 40px" align="center">

                 <BRailAspControls:BRailLabel id="lblMonitor" key="lblMonitor" runat="server"
         Text="BRailLabel" CssClass="textarea">Monitoring</BRailAspControls:BRailLabel>
                                                                                                      53

         </TD>
         </TR>
         <TR>
         <TD>
                 <brailaspcontrols:BRailTextBox id="txtMonitor" runat="server" TextMode="MultiLine"
         Width="568px" Height="400px" CssClass="textarea"></brailaspcontrols:BRailTextBox>

         </TD>
         </TR>
         <tr>
         <td align="center">

                 <brailaspcontrols:BRailButton id="btnCancel" key="btnCancel" runat="server"
         Text="Cancel" CssClass="textarea"></brailaspcontrols:BRailButton>

               <brailaspcontrols:BRailCheckBox id="chkPauze" runat="server" AutoPostBack="True"
       key="chkPauze" Text="Pauze" CssClass="textarea"></brailaspcontrols:BRailCheckBox>
       </td>
       </tr>
       </TABLE>
       </form>
       </body>
</HTML>

De Codebehind zal in stukken worden besproken zodat deze duidelijker wordt:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using BRail.FrameWork.ExceptionManagement.Common;
using BRail.FrameWork.ExceptionManagement.Interfaces;
using BRail.FrameWork.Localization;
using System.Globalization;

Deze zijn de namespaces die worden gebruikt, anders kan men sommige onderdelen niet
gebruiken in de code.
namespace BRail.G153.Import.Gui
{
          /// <summary>
          /// Summary description for Monitor.
          /// </summary>
  public class Monitor : LocalizedPage
  {
    protected BRail.FrameWork.UI.WebControls.BRailLabel lblMonitor;
    protected BRail.FrameWork.UI.WebControls.BRailButton btnCancel;

  CImportProxy myImportProxy;
  ArrayList myArray = new ArrayList();
  protected BRail.FrameWork.UI.WebControls.BRailLabel lblMonitoring;
  protected BRail.FrameWork.UI.WebControls.BRailTextBox txtMonitor;
  ArrayList myControls;
  protected BRail.FrameWork.UI.WebControls.BRailCheckBox chkPauze;
  string lang;

  Hier staan verschillende variabele die worden gebruikt in de code.

  private void Page_Load(object sender, System.EventArgs e)
  {
                                                                                                    54

    if (Session["language"] != null)
   {
          lang = (string) Session["language"];
  }
  else
  {
          lang = "en-gb";
  }
  System.Threading.Thread.CurrentThread.CurrentUICulture=new CultureInfo(lang);

  try
  {
         myImportProxy = (CImportProxy) Application["Thread"];
         myArray = (ArrayList)myImportProxy.myArray.Clone();

         if (myImportProxy.aThread.ThreadState == System.Threading.ThreadState.Running)
         {
                  if (chkPauze.Checked == false)
                  {
                            Response.Write("<META HTTP-EQUIV=\"refresh\"
                  content=\"2;Monitor.aspx\">");

                            chkPauze.Text = "Pauze";
                   }
                   else
                   {
                            chkPauze.Text = "Resume";
                   }

         }

         if (! IsPostBack)
         {
                    myArray.Reverse();

                   foreach(string str in myArray)
                   {
                             txtMonitor.Text += (str + (char)13);
                   }



         }
}
catch(System.NullReferenceException ex)
{
         BRailException newex = new BRailException("Attention there is something wrong!", ex);
}
}

De page_load wordt telkens uitgevoerd als de pagina wordt geladen.
private void btnCancel_Click(object sender, System.EventArgs e)
{
          try
          {


                   if (myImportProxy.aThread.ThreadState != System.Threading.ThreadState.Aborted)
                   {
                            myImportProxy.aThread.Abort();

                            Application["Thread"]= null;

                            Response.Redirect("performance.aspx");
                            GC.Collect();
                                                                                                             55


                  }
         }
         catch(System.SystemException ex)
         {
                  BRailException newex = new BRailException("Attention there is an exception!", ex);
         }

         Deze procedure wordt gebruikt als de gebruiker op de cancel knop klikt.
}

CImportProxy

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
using BRail.G153.Import.Engine.WebReport;

namespace BRail.G153.Import.Gui
{
        /// <summary>
        /// Summary description for CImportProxy.
        /// </summary>

         public class CImportProxy
         {
                   public System.Threading.Thread aThread;

                  public ArrayList myArray;

                  public CImportProxy(string[,] files, DateTime date, string DBS, string DBN, int intType)
                  {


                            string filePer=@"c:\Log.txt";
                            myArray = new ArrayList();
                            ImportWrapper myImport = new ImportWrapper(intType);
                            WriteTextDelegate myDelegate = new WriteTextDelegate(ProcessDelegate);
                            CReport myReport = new CReport(filePer,ref myDelegate);

                            myImport.Prepare(myReport,files, date, DBS, DBN );

                          aThread = new System.Threading.Thread(new
                  System.Threading.ThreadStart(myImport.Go));

                            aThread.Start();

                  }



                  private void ProcessDelegate(string str)
                  {
                            myArray.Add(str);
                  }
         }
}

ImportWrapper
                                                                                                             56


using System;
using BRail.G153.Import.Engine.Import;
using BRail.G153.Import.Engine.InfosParser;
using BRail.G153.Import.Engine.WebReport;

namespace BRail.G153.Import.Gui
{
        /// <summary>
        /// Summary description for ImportWrapper.
        /// </summary>
        public class ImportWrapper
        {

                  private CPresImport _CPresImport;
                  private CSerImport _CSerImport;
                  private CInfosParser _CInfosParser;

                  private string [,] _Files;
                  private System.DateTime _dImplementation;
                  private string _sDBServer;
                  private string _sDBName;
                  private int TypeDoc;



                  public ImportWrapper(int intType)
                  {
                           TypeDoc = intType;
                  }

                  public void Prepare(CReport iReport, string[,] iFiles , System.DateTime dImplementation,
         System.String sDBServer , System.String sDBName )
                  {
                            switch (TypeDoc)
                            {
                                      case 0:
                                                _CPresImport = new CPresImport(iReport);
                                                break;
                                      case 1:
                                                _CSerImport = new CSerImport(iReport);
                                                break;
                                      case 2:
                                                _CInfosParser = new CInfosParser(iFiles, ref
                                      iReport,dImplementation,sDBServer,"D181","D181");
                                                break;

                            }

                            _Files = iFiles;
                            _dImplementation = dImplementation;
                            _sDBName = sDBName;
                            _sDBServer = sDBServer;
                  }

                  public void Go()
                  {
                            switch (TypeDoc)
                            {
                                     case 0:
                                               GoPres();
                                               break;
                                     case 1:
                                               GoSer();
                                               break;
                                     case 2:
                                               GoInfos();
                                               break;
                                                                                             57


                        }
               }


               private void GoPres()
               {
                         _CPresImport.Import(_Files,_dImplementation,_sDBServer,_sDBName);

               }

               private void GoSer()
               {
                         _CSerImport.Import(_Files,_dImplementation,_sDBServer,_sDBName);

               }

               private void GoInfos()
               {
                         _CInfosParser.Import();
               }
       }
}

Omdat CImportProxy en ImportWrapper twee klassen zijn, die gebruikt worden om het
monitoringproces te volgen, zal de uitleg van beide klassen tegelijkertijd gebeuren. Eerst zal
ik een tekening toelichten die de werking van beide klassen uitgelegd.




Figuur 2.4 Werking klassen


Monitor.aspx roept de klasse CImportProxy. CImportProxy maakt een entiteit van
ImportWrapper. CImportProxy heeft een thread die gedurende het hele proces blijft bestaan.
Maar als het proces gedaan is dan zal deze thread niet meer bestaan. ImportWrapper start dit
proces. En geeft informatie terug aan CImportProxy. CImportProxy geeft terug informatie
aan Monitor.aspx. Zo gaat de informatie naar het tekstvak waar alle meldingen van het
proces komen.
58
                                                                                         59



3.     Handleiding G153 (SPS) Admin Tool
Als de toepassing opgestart is dan ziet u volgend scherm.




Figuur 3.1 Welkomscherm


Dit is het welkomscherm van de toepassing. Links ziet u een lijst met drie verschillende
talen. Er wordt Nederlands, Frans en Engels ondersteund zodat elke gebruiker met deze
toepassing kan werken.

Boven de lijst met talen staan linken naar de vier pagina’s die toegankelijk zijn voor de
gebruikers. Indien u op Performance klikt en u selecteert Nederlands als taal dan ziet u het
volgend scherm:

U kan de DB Server en de DB Naam veranderen waar de gegevens moeten geïmporteerd
worden. Deze worden bewaard in een bestand zodat de gebruiker niet telkens dezelfde DB
Server en DB naam moet intypen.
Standaard wordt de dag van vandaag geselecteerd maar de gebruiker kan altijd een andere
datum selecteren. Deze datum wordt gebruikt in de database zodat deze update pas actief
wordt op deze dag. De prestatie root geeft het path weer waar de gebruiker zit met navigeren
in de directorystructuur van de server. Als u het path weet dan kan u dit intypen en op de
knop OK klikken zodat deze map wordt geopend en dan ziet u alle bestanden die deze map
bevat in de lijst met Bestanden.
U kan ook dubbelklikken op de directory’s. Bij een dubbelklik word deze map geopend en
indien deze bestanden bevat, worden deze weergegeven in de lijst met bestanden.
U kan ook bestanden selecteren door op de lijst met bestanden te dubbelklikken of als u
meerdere bestanden in één keer wil selecteren dan selecteert u meerdere bestanden en klikt
u op de knop .
                                                                                       60

U kan ook dubbelklikken op een bestand in de lijst van geselecteerde bestanden. Dit wordt
dan verwijderd. Als u meerdere bestanden wenst te verwijderen dan selecteert u meerdere
bestanden in de lijst van geselecteerde bestanden en klikt u op het knopje met de vuilbak.
Deze bestanden worden enkel uit de lijst verwijderd en niet van de harde schijf.




Figuur 3.2 Prestatiescherm


Als u op Serie klikt dan krijgt u het volgende scherm.




Figuur 3.3 Reeksscherm
                                                                                      61


Dit scherm werkt identiek als het Performance scherm.
Als u op de link van Infos klikt dan krijgt u het volgende scherm dat ook weer hetzelfde
werkt als de twee vorige schermen.




Figuur 3.4 Infosscherm


Enkel de link met Period werkt anders maar omdat die nog niet gebruikt gaat worden en de
gegevens nog niet beschikbaar zijn om dit scherm te laten werken laat ik enkel het scherm
zien en ga ik er niet verder over uitwijden.
                                                                              62




Figuur 3.5 Periodescherm


Vervolgens zal er een kleine demonstratie worden gehouden waarin bestanden worden
geïmporteerd zodat u kunt zien hoe het juist werkt.

Als u bestanden geselecteerd heeft krijgt u het volgende scherm:




Figuur 3.6 Prestatiescherm met geselecteerde bestanden
                                                                                        63

Daarna kan u op de knop Importeer bestanden klikken. Vooraleer het import proces te
starten krijgt de gebruiker volgende melding.




Figuur 3.7 Import bevestiging


Indien de gebruiker op Cancel klikt dan wordt er geen importproces opgestart en gaat de
gebruiker terug naar Performance.

Maar indien de gebruiker op OK klikt dan word het importproces opgestart. Nu ziet de
gebruiker de Monitor waar alle meldingen zichtbaar zijn. Hier kan de gebruiker zien of het
importproces gelukt is en hoe lang dit in beslag nam. Er kan maar één proces tegelijkertijd
opgestart worden. Dus als de gebruiker terug naar performance wil gaan dan zorgt de
toepassing ervoor dat hij enkel de monitor ziet en geen Performancescherm.




Figuur 3.8 Monitorscherm


Op het monitorscherm kan u een vinkje aanklikken bij Pauze/Resume. Dit houdt in dat
wanneer het vinkje aangevinkt staat de gebruiker op zijn gemak kan lezen wat er door de
monitor wordt weergegeven. Indien dit niet aangevinkt is dan wordt er elke seconde een
verversing gedaan van de informatie op het scherm zodat de gebruiker altijd de laatste
informatie heeft over het proces. Als de gebruiker wenst kan hij altijd het proces afbreken
                                                                                     64

door op de knop Afbreken te klikken. Hier word het proces onderbroken en springt u terug
naar het performancescherm.
                                                                                            65



4.     Project Artweb

4.1            Inleiding

Dit deel heeft betrekking op een eerste project dat ik heb uitgevoerd tijdens mijn stage bij de
NMBS. Dit project kadert binnen de Artweb toepassing en het Artemis project.

Het betreft software waarmee de gegevens van Artemis op Intranet kunnen worden
verspreid en via internet Explorer op de PC kunnen worden geraadpleegd.

Het project ARTEMIS Build 1 (informatisering van de nationale dispatching) volgt het
treinverkeer in real time. Daartoe wordt informatie in real-time over de positie van de
treinen naar een informaticasysteem gestuurd dat ze grafisch op scherm voorstelt. Artemis
bestaat uit vier grote delen die in het volgende schema worden voorgesteld.

Roman, Archives en stations vallen buiten de scope van dit deel.

Artemis bestaat uit 6 grote delen:
    170 houdt de veranderingen van het spoornet bij van de dag ervoor. Dit gaat
      vervangen worden door ROMAN. (Nationale Dispatching)
    172 Artweb volgt de treinen op in real-time van 7 dagen geleden en 5 toekomstige
      dagen. (Nationale Dispatching)
    174 Archieven houdt de gegevens bij van heel het jaar. (Nationale Dispatching)
    170 houdt de veranderingen van het spoornet bij van de dag ervoor. Dit gaat
      vervangen worden door ROMAN. (Per station)
    172 Artweb volgt de treinen op in real-time van 7 dagen geleden en 5 toekomstige
      dagen. (Per station)
    174 Archieven houdt de gegevens bij van heel het jaar. (Per station)

Om de gegevens van Artemis beter ter beschikking te kunnen stellen en beter toegankelijk
te maken, werd de Artweb toepassing ontwikkeld.

De basisgegevens van Artemis komen via automatische berichten naar het systeem die
worden gegenereerd door de TNM (Treinnummermelding) en die worden overgeschreven
door speciale apparatuur (IMI Interface met infrastructuur) die is geïnstalleerd in de
relaiszalen van de “hoofdposten”.

Het doel van ARTWEB is de informatie over het treinverkeer van Artemis in een
afzonderlijke database op te nemen en ze te gebruiken voor verspreiding via een
intranettoepassing.

ARTWEB is het resultaat van een geslaagde samenwerking tussen de verschillende directies
die zich hiervoor hebben ingezet: N09 – ICT527 – ICT531 en MI312.
         Algemeen beheer van het project: ir. P. DELCOUR N.09
         Aanleveren van de gegevens van Artemis – coördinatie – analyse – link met
            Oracle database:F. TAIS ICT527
                                                                                          66

          Algemene ontwikkeling van de site – helpbestanden – opvolging ontwikkeling
           en
           feedback: C. WAARDENBURG ICT531
          Verwezenlijking van de interfacesoftware tussen de infrastructuur en Artemis:
           M.SERVAIS MI.312

Omdat nog niet het hele spoorwegnet met TNM is uitgerust, wordt de ontwikkeling van
Artemis wat afgeremd.

Via ARTWEB kunnen ook de gegevens over aankomst, vertrek en doorrit van treinen
manueel in het elektronisch systeem (Artemis Build 1) worden ingevoerd door de
seingevers waar de blokposten gestoord zijn of waar er geen TNM aanwezig is. Alle
gegevens ingevoerd via ARTWEB worden verwerkt in Artemis.

ARTWEB heeft dus de volgende basisfuncties:
    • Invoering van de verkeersgegevens met de computer
    • Invoering van de informatie inzake storingen
    • Raadplegen van het verkeer op:
           • Treinen
           • Stations
           • Dispatchingtafel
           • Groep van treinen
           • Goederentreinen
           • Afgeschafte treinen
    • Rechtvaardigingen en commentaar

De statistiekfunctie wordt ook ontwikkeld.
Er wordt ook onderzocht hoe de gegevens van Artweb automatisch in andere toepassingen
zoals AriBus kunnen worden geladen.

Artweb is al enige tijd in productie maar omdat er elke dag veel gegevens bijkomen en er
ook nog statistieken worden bijgehouden is de performantie niet zo optimaal. Daardoor zijn
de responsetijden voor iedereen niet dezelfde. Er is vooral één onderdeel dat niet performant
is. Dit onderdeel is het beheer dossier.

Beheer dossier maakt het mogelijk om alle dossiers over de vertragingen van treinen op te
vragen. Nadat men een dossier geselecteerd heeft krijgt men verschillende mogelijkheden.

Men kan een dossier wijzigen. Dit houdt in dat men een andere primaire of secundaire
oorzaak invoert van de vertraging. Of dat men een andere status geeft aan het dossier.

Een tweede mogelijkheid is dat men het dossier gaat raadplegen. Hier krijgt men een andere
webpagina met alle informatie over het dossier, men kan afdrukken of exporteren naar de
lokale computer.

Men kan ook twee dossiers linken. Hier kan men dan één of meerdere andere dossiers
linken aan een master dossier. Dit wordt vooral gedaan als het ene dossier een oorzaak kan
zijn voor de vertraging van een andere trein.

Men kan ook de statistieken opvragen van één of meerdere dossiers. Hier krijgt men dan
meer gegevens over het aantal keren dat deze trein te laat was op het traject.
                                                                                         67


De laatste mogelijkheid is het fusioneren van twee of meer dossiers. Na het fusioneren
vormen de dossiers maar één dossier meer. Dit is onomkeerbaar.

Om door de dossiers te gaan, zijn er drie filters aanwezig. De eerste is ten laste van. Dit
houdt in dat men kan selecteren op kosten van welke dienst de trein reed. Als tweede kan
men selecteren op datum. Standaard wordt de dag van vandaag geselecteerd. En de laatste
filter is de status van het dossier.


4.2            Projectopdracht

Omdat Artweb in productie is en een mooie aanvulling vormt op Artemis is het
noodzakelijk dat alle onderdelen zo optimaal mogelijk werken. Waarbij de verbinding met
de webserver en de database server zo snel mogelijk moet gebeuren ook via een
internetverbinding.


De applicatie is ontwikkeld in ASP. Als databasemanagementsysteem wordt Oracle
gebruikt. Via ODBC wordt er met ASP gegevens van de database naar de client gestuurd.

De opdrachtgever heeft gevraagd om in twee stappen te werken. De eerste stap is om een
boodschap weer te geven zodat de gebruiker weet dat de server bezig is en als de server alle
records opgehaald heeft, dan kunnen alle records weergegeven worden. De tweede stap is
om ook een boodschap weer te geven maar van zodra het eerste record opgehaald is en deze
dan onmiddellijk weer te geven. Voor stap twee moet er nog onderzocht worden of dit
mogelijk is.

Het op te leveren resultaat is dat de pagina een merkbare performantiewinst heeft en dat de
gegevens één voor één op het scherm zichtbaar zijn voor de klant.

Er zijn ook enkele risico’s. NMBS is een zeer groot bedrijf en de kans is reëel dat men er
verloren loopt. Daarom moet er voldoende tijd vrijgemaakt worden om een goede inwerking
te waarborgen.

Om de kans op slagen binnen de afgesproken termijn te verhogen worden er een aantal
maatregelen genomen.

Eerst en vooral is er mijn stagebegeleider de heer Luc Frix die ondersteuning geeft.

Voor dagelijkse projectbegeleiding is er steeds de heer Frederic Tais.

Voor vragen over Artweb op vlak van ASP en SQL zijn er specialisten beschikbaar:
Christophe Waardenburg en Vincent Allard.

Voor technische vragen over ASP kan ik terecht bij het ASP Competence Center onder
leiding van Johan Roosen.

Voor technische vragen over Oracle kan ik terecht bij het Oracle Competence Center onder
leiding van Thierry Varenzijn.
                                                                                       68




4.3             Projectorganisatie




Figuur 4.1 Projectorganisatie
De projectleider is Frederic Tais. Hij heeft de verantwoordelijkheid om het project binnen
het termijn af te werken. Christophe Waardenburg en Vincent Allard zijn de programmeurs
die Artweb volledig geprogrammeerd hebben. Aan deze personen kan ik vragen stellen over
hoe Artweb geprogrammeerd is. Bij eventuele vragen over de technologie zijn er altijd de
Competence Centers. Aan deze personen kan ik vragen stellen of iets mogelijk is of niet.


4.4             Planning

                  Opdracht                                     Datum
Opdracht ontvangen                           Donderdag 11 maart 2004
Voorstellen laten zien                       Woensdag 17 maart 2004
Vergadering over beste oplossing             Dinsdag 23 maart 2004
Uitwerking van de bulk collect into +        Woensdag 24 maart 2004
optimalisatie van de stored procedures       Donderdag 25 maart 2004
Uitwerken van een script
Testen van performantiewinst                 Vrijdag 26 maart 2004
                                                                                        69

4.5            Voorbereidend onderzoek

Omdat het project in 2 stappen ingedeeld is heb ik in de eerste stap kennisgemaakt hoe
Artweb is ontwikkeld en welke de standaarden zijn die gevolgd zijn. Een van deze
standaarden is dat er altijd met stored procedures gewerkt wordt en dat er niets hard mag
gecodeerd worden. Ook moet elke toepassing meerdere talen ondersteunen. Er is een
procedure ontwikkeld die helpt bij het ondersteunen van meerdere talen


4.6            Functionele aanpassing

Na het voorbereidend onderzoek zijn er verschillende mogelijkheden om de toepassing te
optimaliseren. Er zijn oplossingen gevonden die kunnen worden gecombineerd om een nog
betere optimalisatie te bekomen zowel op gebied van ASP als op het gebied van de stored
procedures. Er zijn verschillende competent centers die raad geven aan mensen die
problemen hebben op het gebied van de technologie. Deze competent centers nemen dan
samen met de betrokken persoon de problemen door en zoeken dan een geschikte oplossing
zodat de gewenste situatie bekomen wordt. Bij het OCC (Oracle Competent Center) heeft
men vooral oplossingen gevonden op het gebied van de stored procedures. Daarentegen
heeft het .NET CC (.NET Competent Center) oplossingen gevonden die betrekking hadden
op het ASP gedeelte. Nadat ik met deze twee Competent Centers gaan praten ben, heb ik
een selectie gemaakt van de beste oplossingen die hierna zullen besproken worden. Eerst zal
het eerste gedeelde uitgelegd worden en vervolgens de tweede stap.
Stap1: Weergeven van een “Gelieve te wachten” boodschap zodat de gebruiker weet dat de
server gegevens aan het verwerken is. Als de server de gegevens verwerkt heeft, dan
worden alle records getoond op het scherm.

Omdat het een korte stap is, heb ik hier maar 2 mogelijke oplossingen voor gevonden.

Voorstel 1: Met Javascripting (buffer en flush)

Men laat een boodschap zien met Javascripting. Deze boodschap krijgt een label met een
naam zodat men achteraf de boodschap kan verwijderen zodra alle gegevens opgehaald
worden. Hier gebruiken we geen extra pagina zodat de web server geen extra aanvraag moet
verwerken. Dit zou de manier zijn om in heel ARTWEB te werk te gaan.

Ik zal een klein voorbeeld geven dat dit principe beschrijft:

Met Response.Buffer = true kan men een pagina bufferen zodat men zelf kan beslissen
wanneer men iets op het scherm zet met Response.Flush(). Hier kan men de stream van
gegevens op de Webpagina goed onder controle houden. Dit voorbeeld geeft eerst de
boodschap “Gelieve te wachten aub. De server is de gegevens aan het ophalen”. Daarna telt
het drie keer van 0 tot 1.000.000 en geeft drie keer een boodschap “Message *” weer. Dit
wordt bekomen omdat men op het laatste een Response.Flush doet. En natuurlijk wordt de
boodschap verwijderd met javascript dankzij “label.style.display = "none" ;”.

Voorbeel 1: Javascript

<% Response.Buffer = true %>
                                                                                       70

<html>
<body>

<h3 id="label">Gelieve te wachten aub. De server is de gegevens aan het ophalen</h3>

<%
  Response.Flush ()

     for i = 0 to 1000000
         a=a+1
     next
%>
<h3>Message 1</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next

%>
<h3>Message 2</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next
%>
<h3>Message 3</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next

     Response.Flush
%>

<script language="javascript">
label.style.display = "none" ;
</script>

</body>
</html>

Voorstel 2: Met een extra pagina

Hier wordt een extra pagina gebruikt. Deze pagina bevat de boodschap en via
Location.Replace wordt de pagina met de gegevens opgehaald. Maar de pagina met de
gegevens wordt enkel weergegeven als al de gegevens zijn opgehaald. Zolang dit niet
voltooid is, blijft de boodschap zichtbaar.

Ik zal een eenvoudig voorbeeld uitlegen die deze principe beschrijft:
                                                                                       71

Deze pagina geeft de boodschap “Gelieve te wachten aub. De server is de gegevens aan het
ophalen!”. Terwijl de boodschap zichtbaar is voor de gebruiker haalt deze pagina een
tweede pagina op met de functie “location.replace("pagina2.asp")”. Zodra de gegevens zijn
opgehaald, wordt de tweede pagina weergegeven. Ter illustratie telt de tweede pagina drie
keer van 0 tot 1.000.000 en geeft drie boodschappen weer op het scherm.

Voorbeeld 2: Met een extra pagina

Pagina 1:

<h3>Gelieve te wachten aub. De server is de gegevens aan het ophalen!</h3></br></br>
<script language="javascript">
location.replace("takeslong.asp")
</script>

Pagina 2:

<html>
<body>
<%
   for i = 0 to 1000000
       a=a+1
   next
%>
<h3>Message 1</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next
%>
<h3>Message 2</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next
%>
<h3>Message 3</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next

%>
</body>
</html>

Dit waren de voorstellen voor de eerste stap. Nu zullen de voorstellen voor de tweede stap
uitgelegd worden.
                                                                                         72

Stap 2: Weergeven van een boodschap en telkens als er een record opgehaald is, wordt deze
weergegeven op de webpagina. Deze stap heb ik moeten onderzoeken of dit mogelijk is en
wat de voor- en nadelen zijn van deze methoden.

Voorstel 1: Bufferen en Flushen:

Men laat een boodschap zien met javascripting. Deze boodschap krijgt een label met een
naam zodat men achteraf de boodschap kan verwijderen zodra het eerste record opgehaald
is. Hier gebruiken we geen extra pagina zodat de webserver geen extra aanvraag moet
verwerken. Een groot nadeel is dat er voor elk record een connectie met de database en met
de webserver moet gemaakt worden zodat die veel overhead bezorgt aan het netwerk en de
database server overbelast. Een database is niet gemaakt om veel connecties te maken en
telkens maar één record op te halen. Het is gemaakt om weinig connecties te maken maar
veel records per keer over het netwerk te sturen.

Ik zal een klein voorbeeld geven dat dit principe beschrijft:

Met Response.Buffer = true kan men een pagina bufferen zodat men zelf kan beslissen
wanneer men iets op het scherm zet met Response.Flush(). Hier kan men de stream van
gegevens op de Webpagina goed onder controle houden. Dit voorbeeld geeft eerst de
boodschap “Gelieve te wachten aub. De server is de gegevens aan het ophalen”. Daarna telt
het vier keer van 0 tot 1.000.000 en geeft vier keer een boodschap “Message *” weer. Dit
wordt bekomen omdat men na elke blok een Response.Flush doet. En natuurlijk wordt de
boodschap verwijderd met javascript dankzij “label.style.display = "none" ;” zodra de eerste
boodschap “Message” zichtbaar is.

Voorbeeld 3: Bufferen en Flushen

<% Response.Buffer = true %>

<html>
<body>

<h3 id="label">Gelieve te wachten aub. De server is de gegevens aan het ophalen</h3>

<%
  Response.Flush ()

   for i = 0 to 1000000
       a=a+1
   next

   Response.Flush ()
%>
<script language="javascript">
label.style.display = "none" ;
</script>

<h3>Message 1</h3>
<%
   for i = 0 to 1000000
                                                                                     73

        a=a+1
     next

     Response.Flush ()

%>
<h3>Message 2</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next

    Response.Flush ()
%>
<h3>Message 3</h3>
<%
   for i = 0 to 1000000
       a=a+1
   next

     Response.Flush
%>
<h3>Message 4</h3>

<%
     for i = 0 to 1000000
         a=a+1
     next


%>

<script language="javascript">
label.style.display = "none" ;
</script>

</body>
</html>


Dit is het enige voorstel dat ik heb gevonden om deze manier van werken te bekomen.
De volgende voorstellen hebben betrekking op het optimaliseren van de hele ARTWEB
toepassing met de nadruk op de “Beheer dossier” functie.

Optimalisatie van de webtoepassing:

Voorstel 1: Views gebruiken in plaats van Stored procedures:

Een view kan het doorsturen van gegevens versnellen. In een view kan men ook
berekeningen maken zodat de databewerking in de view zelf kan gebeuren. Alle statements
die men in een select kan gebruiken kan men ook in een view gebruiken dus heeft men geen
                                                                                       74

beperkingen door een view te gebruiken. Een view kan ook dynamisch gemaakt worden
zodat er een automatische update kan gebeuren van de view bij een verandering van de
brongegevens.

Voorstel 2: Bulk Collect Into gebruiken in de stored procedures

Bij gebruik van “Bulk Collect Into“ in de stored procedures worden de gegevens in andere
variabelen bewaard. Deze nieuwe variabelen zullen veel kleiner zijn dan de originele
gegevens zodat er veel minder gegevens moeten doorgestuurd worden naar de client.
Vanzelfsprekend zal ook de verbinding met de databaseserver veel sneller verlopen omdat
deze minder gegevens moet doorsturen.

Voorstel 3: OO4O

OO4O is een andere manier om de database aan te spreken. In ARTWEB gebruikt men
ODBC. Maar het is mogelijk om OO4O in één pagina te gebruiken. Omdat OO4O van
Oracle is zal deze de verbinding met de database versnellen.

Voorstel 4: De SQL statements hard coderen in de webapplicatie

De SQL statements in de ASP code steken zodat men altijd kan controleren hoeveel records
er worden doorgestuurd naar de client. Maar een nadeel kan zijn dat men zelf moet
controleren dat alle records worden opgehaald via de eigenschappen van de recordset. Het
grootste nadeel is dat wanneer men SQL statements in de ASP code steekt deze toegankelijk
zijn voor gebruikers met alle gevolgen dat dit met zich meebrengt. Nog een nadeel is dat
wanneer er een aanpassing moet gebeuren aan de SQL statements deze moet gebeuren in
elke pagina die deze SQL statements gebruikt.

Voorstel 5: Berekende gegevens opslaan in een tabel

Als men nu al de berekende gegevens zou bewaren in een tabel van de database zou dit geen
berekentijd meer kosten. Als men dan de berekende gegevens nodig heeft dan kan men deze
direct benaderen zonder de berekening op de database server uit te voeren. Bij een update
van de brongegevens kan men door een trigger die de webapplicatie oproept de gegevens
herberekenen.

Voorstel 6: Eerst de gewone gegevens weergeven en daarna de berekende gegevens
weergeven.

Misschien kan men de gegevens in twee delen laten zien. Eerst laat men de gewone
gegevens zien zodat de gebruiker al kan werken met de gegevens die hij ziet. Maar van
zodra de gegevens berekend zijn laat men al de gegevens zien. Het zou de performantie niet
verhogen maar de gebruiker denkt dat het snel gaat omdat hij al met een deel van de
gegevens kan werken. Maar omdat er twee stored procedures uitgevoerd moeten worden om
één maal het resultaat te zien zal deze de overhead van de server vergroten met nadelige
gevolgen. De server zal trager zijn en er zullen meer gegevens over het netwerk moeten
worden gestuurd.

Dit waren al de voorstellen die ik heb gedaan aan de Heer Tais. We hebben samen overlegd
en de beste oplossingen weerhouden. Deze kunt u vinden in de praktische uitwerking. Hier
zult u ook de reden vinden waarom een voorstel niet weerhouden is.
                                                                                        75




4.7              Praktische uitwerking

In dit gedeelte zal de praktische uitwerking aan de orde zijn. Het zal de veranderingen aan
de ASP pagina weergeven, de database en de stored procedures. Maar eerst zal ik de
voorstellen beschrijven die we weerhouden hebben en hoe deze toegepast zijn is de praktijk.

Stap 1:

Voorstel 1 is weerhouden. Hier gaat men met javascripting een boodschap weergeven en als
alle records opgehaald zijn zal deze boodschap weer verwijderd worden. We hebben voor
deze oplossing gekozen omdat dit de manier is om in de toekomst met ARTWEB te werken.
Deze methode hoeft ook geen extra pagina aan te vragen zoals bij voorstel 2. Daardoor zal
er geen performantievermindering optreden. Ook zal deze methode uitgebreid worden met
een boodschap wanneer er geen gegevens zijn gevonden bij een selectie van de gebruiker.
Dan weet de gebruiker wanneer de toepassing klaar is met het verwerken van de aanvraag.

Stap2:

Voorstel 1 werd niet weerhouden omdat onderzoek aantoonde dat record per record ophalen
niet doenbaar is voor deze webtoepassing. Daarom zal men alle records in één keer
weergeven en proberen de performantie op te krikken via de optimalisatievoorstellen.

Optimalisatie:

Voorstel 1 werd niet weerhouden omdat het gebruik van views in dit geval geen
optimalisatie tot gevolg gaat hebben omdat het gebruik van stored procedures even snel is
als het gebruik van views.

Voorstel 2 werd weerhouden omdat het gebruik van “Bulk collect into” in de stored
procedures een grote performantiewinst zal teweeg brengen zodat dit al een grote
verbetering vormt in vergelijking met daarvoor.

Voorstel 3 werd niet weerhouden omdat OO4O geen standaard vormt bij de NMBS en deze
zal zeker geen performantiewinst met zich meebrengen omdat ook alle stored procedures
moeten aangepast worden om gebruik te maken met OO4O. Daardoor zal de inspanning te
groot zijn voor het te behalen resultaat.

Voorstel 4 werd niet weerhouden omdat dit een te groot risico vormt als er een stored
procedure aangepast moet worden dan moet dit in elke pagina worden aangepast. En de
gebruikers kunnen aan de HTML code en ook aan de stored procedures.

Voorstel 5 werd niet weerhouden omdat de gegevens worden berekend voordat ze worden
opgeslagen in de tabel dus eigelijk zitten de berekende gegevens al in een tabel.

Voorstel 6 werd ook niet weerhouden omdat men dan twee keer de databaseserver moet
aanspreken om éénmaal de gegevens te zien en daardoor zal er veel overhead zijn bij zowel
de databaseserver als de webserver als het netwerk.
                                                                                           76

Maar als extra voorstel werd er opgemerkt dat de stored procedures op alle mogelijke
manieren mogen aangepast worden als er maar performantie winst is. De aanpassingen
zullen gebeuren op gebied van hoe de stored procedures geschreven zijn en er zullen zoveel
mogelijk functies worden gebruikt die performantiewinst garanderen binnen Oracle.

In de volgende paragraaf worden voorbeelden uitgelegd van ARTWEB en welke
aanpassingen er zijn gebeurd.


4.8            Resultaat

Eerst zullen de stored procedures worden uitgelegd, met een illustratie worden dan de
aanpassingen geïllustreerd Daarna zullen de veranderingen in de ASP code worden
toegelicht met de pagina van Beheer dossier. Daarna zullen de aanpassingen aan de database
uitgelegd worden.

Er worden veel stored procedures gebruikt in ARTWEB. Meestal zijn deze stored
procedures niet eenvoudig omdat er redelijk veel bewerkingen moeten gebeuren op de
gegevens vooraleer deze zichtbaar zijn voor de gebruiker.

Eerst zal ik de “Bulk collect into” aanpassingen uitleggen. In de meeste gevallen worden
cursoren gebruikt in de stored procedures van ARTWEB. Een cursor is een verzameling van
variabelen die een waarde krijgen van de database. Deze variabelen kan men sequentieel
aanspreken. Dit wil zeggen dat men de waarde achtereenvolgens opvraagt om deze te tonen
aan de gebruiker. Maar omdat men Bulk collect into wil gebruiken hoeven we de cursoren
niet te veranderen wat een groot pluspunt is. We hoeven enkel de manier waarop de cursor
wordt geopend en wordt gebruikt te veranderen.

Ik zal een klein voorbeeld geven met de manier die vroeger werd toegepast en de manier die
nu wordt gehanteerd.

Vroeger gebruikte men:

        FOR mycursor IN c_cur(pin_utilisateur_id ,pin_groep_id,pin_statut_id ,piv_datum)
         LOOP
              pov_element(l_cur_count) := mycursor.de;
               pov_datum(l_cur_count) := mycursor.hr;
               pov_dossier_no(l_cur_count) := mycursor.Dno;
               pon_disturb_id(l_cur_count) := mycursor.Did;
               pov_name_fr(l_cur_count) := mycursor.nom;
               pov_name_nl(l_cur_count) := mycursor.naam;
               pon_utilisateur_id(l_cur_count) := mycursor.nptcar;
               pon_hkv(l_cur_count) := mycursor.hkv;
               pon_hkv_rt(l_cur_count) := mycursor.hkv_rt;
               pon_hkv_sup(l_cur_count) := mycursor.hkv_sup;
               pon_hkm(l_cur_count) := mycursor.hkm;
               pon_hkm_rt(l_cur_count) := mycursor.hkm_rt;
               pon_hkm_sup(l_cur_count) := mycursor.hkm_sup;
               pov_stat(l_cur_count) := mycursor.stat;

De cursor werd niet expliciet geopend en gesloten. Dus kan men niet nagaan of de cursor
geopend is of gesloten is. Men kan ook niet nagaan of er problemen zijn opgetreden bij het
verwerken van de cursor. Ook moest de hele cursor doorlopen worden met de FOR LOOP
                                                                                                             77

die elk record in de verschillende variabellen kopieert. Dit nam aanzienlijk heel wat tijd in
beslag.

Maar dankzij de Bulk collect into methode krijgt men het volgende:

OPEN c_cur(pin_utilisateur_id, pin_groep_id, pin_statut_id, piv_datum);

FETCH c_cur BULK COLLECT INTO
      pon_disturb_id,
      pov_dossier_no,
      pov_datum,
      pov_name_fr,
      pov_name_nl,
      pov_element,
      pon_utilisateur_id,
      pon_hkv,
      pon_hkv_rt,
      pon_hkv_sup,
      pon_hkm,
      pon_hkm_rt,
      pon_hkm_sup,
      pov_stat,
      pov_type;

CLOSE c_cur;

De cursor wordt expliciet geopend en gesloten. En met de Fetch c_cur BULK COLLECT
INTO worden er in één doorgang alle records in de lijst van variabellen gekopieerd. En
bovendien wordt de waarde nog verkleind ook zodat het veel sneller over het netwerk kan
gestuurd worden. Deze aanpassing is bij alle stored procedures uitgevoerd die in ARTWEB
gebruikt worden.

Nu zullen de aanpassingen aan de ASP pagina uitlegt worden.

Er zijn verschillende aanpassingen gebeurd aan de pagina. De eerste aanpassing was een
boodschap “Please wait” weer te geven. Deze boodschap verandert naargelang de gebruiker
een andere taal kiest. De gebruiker heeft keuze tussen Nederlands of Frans. Ik heb daarvoor
onderstaande code toegevoegd aan de pagina:

<!-- geeft de please wait boodschap naargelang de taal -->
  <div id=mydiv align="" style="Z-Index:1;position: absolute; top: 100; text-align: center; width: 100% ">
    <h2 align="CENTER"><%=(dict.LookupValue(l & "rawode"))%></h2>
  </div>

Deze code drukt een boodschap op het scherm die overeenkomt met “rawode”. Dit wil
zeggen dat de methode “dict.LookupValue(l & “rawode”)” de waarde gaat zoeken in dict.txt
met als variabelen l wat staat voor language en als key “rawode”. Alle vertalingen staan in
een tekstbestand. Het tekstbestand bestaat uit lijnen die opgebouwd zijn uit een taal een key
en een waarde. Deze waarde zal in de boodschap zichtbaar zijn. De taal worddt voorgesteld
door een cijfer. 0 is Frans en 1 is Nederlands.

Vb:
0rawode, Un peu de patience SVP ...
1rawode, Even geduld AUB ...
                                                                                                       78

Hier is het voorbeeld dat in de code wordt gebruikt. In het geval de taal Nederlands zou zijn
dan zou l = 1 en dan komt er “Even geduld AUB ...” op het scherm.

De volgende aanpassing had betrekking op een boodschap die werd getoond wanneer er
geen records werden gevonden in de database.

Daarvoor heb ik volgende code toegevoegd aan de pagina:


 if ds.eof Then ' no result
     Set cmdStoredProc = nothing
    ds.close
    set ds = nothing
    conn.close
    set conn = nothing

 %>

         <!-- geeft een boodschap dat er niets gevonden is naargelang de taal -->
                  <div name="niets" style="z-index:1; left: 200; top: 100;POSITION: absolute; text-align:
center; width: 50%; background-color: 99CCFF; border-color: Navy; border-style: solid; border-width: thin;
">
                           <h2                               align="CENTER"><br><%=(dict.LookupValue(l
&"msg_erreur_result"))%></h2>
                  </div>

                <!--- Bouton modifier --->
                <BUTTON disabled             ID="Bt_Pert_Exist" CLASS="ButtonUp" TITLE="<%=
(dict.LookupValue(l &"modifier_dossier"))%>" STYLE="POSITION: absolute; LEFT: 5px; TOP: 326px;
VISIBILITY: visible"; ><B><%= (dict.LookupValue(l &"Mgras"))%><%= (dict.LookupValue(l
&"modi"))%></B></BUTTON>


               <!--- Bouton consulter dos --->
               <BUTTON disabled onclick="consult()"          ID="Bt_consult" CLASS="ButtonUp"
TITLE="<%= (dict.LookupValue(l &"consulter_dossier"))%>" STYLE="POSITION: absolute; LEFT: 135px;
TOP: 326px; VISIBILITY: visible"><B><%= (dict.LookupValue(l &"3"))%></B></BUTTON>

               <!--- Bouton Liens --->
               <BUTTON        disabled   onclick="lier()"       ID="Bt_liens" CLASS="ButtonUp"
TITLE="<%=dict.lookupvalue(l &"lier_dossiers")%>" STYLE="POSITION: absolute; LEFT: 265px; TOP:
326px; VISIBILITY: visible"><B><%= (dict.LookupValue(l &"liens"))%></B></BUTTON>

                <!--- Bouton Terminer --->
                <%lien = "menu.asp?pw=" & pw %>
                <div STYLE="POSITION: absolute;LEFT: 655px; TOP: 330px;"><a href="#"
onclick="closewin();return false;"><b><%= (dict.LookupValue(l &"109")) %></b></a></div>
                <!--<BUTTON onclick=Terminer() ACCESSKEY="M" ID="Bt_Terminer" TITLE="<%=
(dict.LookupValue(l &"ttip_terminer"))%>" STYLE="POSITION: absolute; WIDTH: 105;LEFT: 525px;
TOP: 190px; background:white;"><U><%= (dict.LookupValue(l &"109")) %></U></BUTTON>-->

                 <% if session("fonction_2") = "Yes" then

                %>               <!--<BUTTON       onclick="modif_stat()"         ID="Bt_stat"
CLASS="ButtonUp" TITLE="<%= (dict.LookupValue(l &"modifier_stat"))%>" STYLE="POSITION:
absolute; LEFT: 395px; TOP: 326px; VISIBILITY: visible"><B><%= (dict.LookupValue(l
&"112"))%></B></BUTTON>-->
                                 <input disabled type=submit CLASS="ButtonUp" TITLE="<%=
(dict.LookupValue(l &"modifier_stat"))%>" STYLE="POSITION: absolute; LEFT: 395px; TOP: 326px;
                                                                                                79

VISIBILITY: visible; font-weight:bold;" Value="<%= (dict.LookupValue(l &"112"))%>" id=submit1
name=submit1>
              <%
              end if
              %>

                <!--- Bouton Fusion dossier--->
                <%if (session("fonction_14") = "Yes") OR (session("fonction_15") = "Yes")then

                %>
                      <BUTTON disabled onclick="fusion()"          ID="Bt_stat" CLASS="ButtonUp"
TITLE="<%= (dict.LookupValue(l &"fusion_dossiers"))%>" STYLE="POSITION: absolute; LEFT: 525px;
TOP: 326px; VISIBILITY: visible"><B><%= dict.lookupvalue(l & "fusion_dossier")%></B></BUTTON>
               <%
               end if
               %>


                </body>
                </html>
        <%

        response.end


       end if

%>

Eerst controleer ik of er records zitten in de recordset met “if ds.eof Then”. Is dit het geval
dan wordt de then tak uitgevoerd. De connectie en de recordset worden gesloten en uit het
geheugen verwijderd. Dan laat ik een boodschap zien die zegt dat er geen records zijn
gevonden. Deze boodschap is weer in meerdere talen beschikbaar zoals het voorbeeld
hierboven. Dan worden alle knoppen op het scherm gezet maar zijn deze niet toegankelijk,
zodat de gebruiker niet op de knoppen kan klikken als er geen gegevens zijn om te
bewerken. Ik zal een voorbeeld geven van een knop:

<!--- Bouton modifier --->
                <BUTTON disabled             ID="Bt_Pert_Exist" CLASS="ButtonUp" TITLE="<%=
(dict.LookupValue(l &"modifier_dossier"))%>" STYLE="POSITION: absolute; LEFT: 5px; TOP: 326px;
VISIBILITY: visible"; ><B><%= (dict.LookupValue(l &"Mgras"))%><%= (dict.LookupValue(l
&"modi"))%></B></BUTTON>

Deze knop is disabled zodat deze niet toegankelijk is voor de gebruiker. De opdruk op de
knop is ook in meerdere talen beschikbaar. Naargelang van de gekozen taal zal er iets
anders op de knop staan.

Dit zijn de aanpassingen die ik heb gedaan aan de ASP pagina.

Nu zal ik de aanpassingen behandelen die aan de database zijn gedaan om een betere
performantie te verkrijgen.

Er zal nu een beeld geschets worden van vroeger en alle aanpassingen zullen daarna
uitgelegd worden.
                                                                                        80

Vroeger:

Vroeger had men een tabel “Liens_Dossiers”. In deze tabel zitten volgende velden
Liens_ID, Maitre_ID en Esclave_ID. Er was ook een tabel “Disturbance”. Deze had
volgende velden Disturb_ID, Disturb_Type_ID, Dossier_No. Schematisch stelt dit het
volgende voor:


   Liens_Dossiers                                      Disturbance
      Liens_ID                                          Disturb_ID
     Maitre_ID                                       Disturb_Type_ID
     Esclave_ID                                        Dossier_No

In de toepassing kunnen dossiers voorkomen die meester zijn van andere dossiers die slaaf
zijn. Dit wordt gedaan omdat een slaafdossier een oorzaak kan zijn dat een meesterdossier
bestaat. Vb: een slaafdossier bevat een trein die 5 min vertraging heeft. Deze trein zal na
zijn rit herbruikt worden in een andere rit. Maar doordat de trein al 5 minuten vertraging
heeft zal de volgende rit ook 5 min vertraging hebben. Dan kan men stellen dat het tweede
dossier een meester is van het eerste.

Nu:

Liens_Dossiers is verwijderd en hebben we een veldje in Disturbance toegevoegd dat
Master_ID noemt. Master_ID = Disturb_ID indien het een zelfstandig dossier is. Master_ID
= null als het een meester is. En als het een slaaf is dan zit er een andere Disturb_ID in.

Een zelfstandig dossier is een dossier dat geen relatie heeft met andere dossiers.
Schematisch zien de tabellen er nu zo uit:


   Liens_Dossiers                                      Disturbance
      Liens_ID                                          Disturb_ID
     Maitre_ID                                       Disturb_Type_ID
     Esclave_ID                                        Dossier_No
                                                        Master_ID


Omdat deze verandering in de database gebeurd, moeten alle gegevens die in Liens-Dossiers
zitten behouden blijven. Hiervoor heb ik een update script geschreven die deze gegevens
naar de tabel Disturbance omzet. De script ziet er als volgt uit:

UPDATE DISTURBANCE
      SET master_id = disturb_id
      WHERE disturb_id NOT IN (SELECT maitre_id FROM LIENS_DOSSIERS)
      AND disturb_id NOT IN (SELECT esclave_id FROM LIENS_DOSSIERS);

UPDATE DISTURBANCE
     SET master_id =
                     (SELECT ld.maitre_id FROM LIENS_DOSSIERS ld
                     WHERE disturb_id = ld.esclave_id)
     WHERE disturb_id IN (SELECT ls.esclave_id FROM LIENS_DOSSIERS ls      );
                                                                                       81

Eerst worden de zelfstandige dossiers geüpdatet. Dit wordt gedaan door alle Master_ID’s
gelijk te stellen aan Disturb_Id, voor alle Disturb_ID’s die niet in Liens_Dossiers
voorkomen.

Daarna worden de slaven geüpdatet. Hun Master_ID wordt gelijkgesteld aan de Maitre_ID
uit Liens_Dossiers.

Nu blijven enkel nog de Meesters over. Maar omdat de standaardwaarde van een veld in een
database null is blijven enkel nog Meesters over met hun Master_ID gelijk aan null.

Door deze aanpassing heb ik ook verschillende Stored procedures moeten aanpassen om aan
de nieuwe structuur van de tabellen te voldoen.

In bijlage vindt u de volledige code van de ASP pagina en alle stored procedures die
aangepast zijn om deze performantiewinst te halen.


4.9           Besluit

Al deze aanpassingen hebben geleid tot een grote performantieverbetering. Voor de
aanpassingen duurde het ophalen en weergeven van gegevens soms 30 seconden of meer
maar na de aanpassing was deze transactie binnen een paar seconden opgehaald en kon de
gebruiker verder werken. Dit is een grote verbetering zodat de heer Tais zeer tevreden was
over de aanpassingen en de nieuwe performantie van het Beheer dossier pagina.
                                                                                   82



5.     Handleiding ARTWEB onderdeel “Beheer Dossier”
Als men ARTWEB opent dan komt men in het volgende scherm.




Figuur 5.1 Artweb welkomscherm


Hier kan men de taal kiezen en het aantal gebruikers zien die ARTWEB aan het gebruiken
zijn.

Als men de Nederlandse versie kiest dan komt men in het loginscherm.
                         83




Figuur 5.2 Loginscherm
                                                                                   84

Na het inloggen komt men op het menuscherm terecht waar de verschillende onderdelen al
of niet beschikbaar zijn naargelang de gebruikersnaam.




Figuur 5.3 Menuscherm


Met de optie “Beheer dossier” in de rand, krijgt de gebruiker volgend scherm:




Figuur 5.4 Beheer dossier
                                                                                          85


Dit scherm geeft de lijst van dossiers.
Volgens de Login, geeft de lijst:

       Voor een gewone controlepost, alleen de dossiers die door deze controlepost zijn
        aangemaakt.

       Voor een hoofd controlepost, de dossiers die door deze post zijn aangemaakt alsook
        die van de ervan afhangende PTKAR voor een bureau "Algemeen toezicht", de
        dossiers die zijn aangemaakt door elke controlepost van de regio.

       Voor een bediende van een dispatching, alleen de dossiers die door deze
        Dispatchingtafel zijn aangemaakt.

Weergave criteria

Met de lijst “Ten laste van” kunnen de weergegeven dossiers worden beperkt tot bepaalde
Verantwoordelijkheidscriteria. Standaard worden alle dossiers weergegeven.

Met de lijst “Datum” kan een dag worden gekozen onder de laatste 30 dagen. Standaard
worden alle dagen weergegeven.

De lijst “Statuut” stelt een selectie voor volgens een statuutkeuze. Standaard worden enkel
de
dossiers met het statuut "open" weergegeven.
In de lijst “Statuut”:

              hebben de blokposten de keuze tussen “open”en “gesloten”
              hebben de bureaus “Algemeen toezicht” van de regio de keuze tussen “open,
               gesloten, goedgekeurd N5, goedgekeurd N5 en N5 geweigerd N4”. Ook
               heeft de dispatching de keuze tussen “open”en “gesloten”
              heeft het bureau “Algemeen toezicht” van de NDN (nationale dispatching) de
               keuze tussen “open, gesloten, goedgekeurd AT NDN, ATNDN geweigerd
               N4”.

Weergegeven gegevens

De volgende kolommen worden weergegeven:
    Dossier: het nummer van het dossier
    Datum: de creatiedatum van het dossier
    Type: het type van storing
    Titel: identificatie van het dossier
    HKV: de som van de reizigerstreinen voor dit dossier
    rtHKV: de som van de vertragingen van de reizigerstreinen voor dit dossier
    afgHKV: aantal afgeschafte reizigerstreinen voor dit dossier
    HKM: de som van de goederentreinen voor dit dossier
    rtHKM: de som van de vertragingen van de goederentreinen voor dit dossier
    afgHKM: aantal afgeschafte goederentreinen voor dit dossier
    TY: dossiertype: O = onafhankelijk, S = slaaf, M = meester
                                                                                          86

      Stat: een tag (Y = ja / N = nee) die aangeeft of het dossier in de statistieken is
       opgenomen

Dossiers op een rode achtergrond staan voor treinen waarvan de vertraging hoger ligt dan 40
minuten of die zijn afgeschaft.

U selecteert een dossier door erop te klikken en vervolgens op een van de onderstaande
knoppen te klikken: Wijzigen, Raadplegen, Linken, Statistieken of Fusie dossiers of op de
optie Terug menu. Die knoppen zijn alleen zichtbaar voor de gebruikers die daartoe de
toelating hebben
(Login).

Het is tevens mogelijk het statuut van verschillende dossiers gelijktijdig te veranderen.
Daartoe volstaat het de gewenste dossiers te selecteren door erop te klikken en op de knop
"Wijzigen" te klikken. Via een rollijst met de mogelijke keuzes, kunt u het statuut van de
geselecteerde dossiers wijzigen.

Dossier wijzigen
Het doel van deze functie is de inhoud van een dossier wijzigen of aanvullen:

Met een klik op de knop "Wijzigen" krijgt u volgend scherm:




Figuur 5.5 Wijzigingscherm


Dit scherm is gelijkaardig met dat voor de invoering van een primaire storing en is al
ingevuld met de gegevens die vroeger voor dit dossier werden ingevoerd. De werking is
gelijkaardig met die van het scherm voor de invoering van een primaire storing. Door te
klikken in de rechterlijst verschijnen in de linkse de oorzaken van de betrokken storing. Het
volstaat erop te klikken om te selecteren.

In het veld "Titel" kan de dossiertitel worden veranderd. Klik op de knop "Vrije tekst": u
krijgt een veld waarin u de dossiertekst kunt aanpassen. In dit scherm vindt u een
bijkomende lijst "Stat." waarin het statuut van het dossier kan worden veranderd.
      Een blokpost kan een dossier sluiten of opnieuw openen
      Een bureau Algemeen toezicht kan op zijn niveau een dossier opnieuw openen,
        sluiten of goedkeuren
      Een dispatching (3 x 8) kan een dossier opnieuw openen of sluiten
                                                                                            87

       Het algemeen toezicht van de dispatching kan op haar niveau een dossier
        goedkeuren.

De knop "Bewaren" registreert uw wijzigingen.



Het veld                 geeft het aantal dagen aan dat dit samengestelde dossier bestaat.
    Bij een samengesteld dossier kan men de titel , het dossiernummer, de
       verantwoordelijke dienst.... enkel wijzigen als het oorspronkelijke dossier
       geselecteerd wordt . Bij de gekopieerde dossiers kan enkel de vrije tekst en het
       statuut                              gewijzigd                              worden.




Figuur 5.6 Statusscherm
• Het is tevens mogelijk het statuut van verschillende dossiers gelijktijdig te veranderen.
Daartoe volstaat het de gewenste dossiers te selecteren in het scherm "Beheer dossiers" door
erop te klikken en op de knop "Wijzigen" te klikken. Via een rollijst met de mogelijke
keuzes, kunt u het statuut van de geselecteerde dossiers wijzigen.

Dossier raadplegen

Het raadpleegscherm van een dossier is het volgende:




Figuur 5.7 Rapportscherm


Dit scherm geeft de verschillende inlichtingen die al werden ingevoerd inzake de storing.
                                                                                            88

Met de knop "Export" kunt u de gegevens bewaren op uw harde schijf in formaat HTML
voor later gebruik.
De precieze tekst van het relaas van de storing wordt maar onder de titel van het dossier
weergegeven wanneer dit laatste werd goedgekeurd door het bureau algemeen toezicht van
de regio.
In het geval het dossier over verschillende dagen loopt (samengesteld dossier), worden de
verschillende inlichtingen onder de titel gegroepeerd per dag met opgave van de datum als
scheiding.
Door op de pijlen te klikken gaat u naar het volgende/vorige dossier.

Linken dossiers

Definities

meesterdossier: hoofddossier aangemaakt door de persoon die het relaas moet
opstellen. Een dossier wordt meester nadat er een ander aan werd gelinkd. Een link is een
logische verbinding tussen twee of meer dossiers.

slaafdossier: dossier dat aan een meesterdossier gekoppeld is. In het slaafdossier worden de
plaatselijke gevolgen vermeld. (Enkel de vrije tekst en het statuut kunnen gewijzigd
worden.)

samengesteld dossier: dossier dat over verschillende dagen loopt. Het dossier van de eerste
dag wordt "origineel dossier" genoemd. De kopieën heten "gedupliceerde dossiers".

Voorbeeld:
Een overweg is gestoord tussen de stations Roos en Tulp. In elk station wordt een dossier
gecreëerd. Het station Roos controleert deze overweg en moet normaal een D43 opstellen
met
alle gevolgen voor de treindienst. De twee dossiers kunnen dus worden gekoppeld.
Aangezien Roos de overweg controleert, moet het de dossiers koppelen (= linken) (het
dossier van Roos wordt "Meester", dat van Tulp wordt "Slaaf").

Beschrijving van de functie
In het scherm "Beheer dossiers" kunt u met de knop "Linken" de slaafdossiers raadplegen
van
een geselecteerd meesterdossier, een link met bepaalde slaafdossiers verbreken, of aan het
meesterdossier een of meer slaafdossiers toevoegen.

De knop "Linken" is alleen actief wanneer de gebruiker een van zijn eigen dossiers
selecteert
die geen slaaf is. Hij opent een venster waarin de slaafdossiers voor het geselecteerde
dossier wordt weergegeven. Elk slaafdossier kan worden geconsulteerd via een klik op zijn
dossiernummer. Naast elk slaafdossier vindt u een link "unlink". Via die "link" kunt u de
link
tussen dat slaafdossier en het meesterdossier opheffen. Het slaafdossier wordt opnieuw
onafhankelijk en het veld "Statistiek" van het scherm "Beheer dossier" wordt "Y".
Om een slaafdossier aan een meesterdossier toe te voegen, moet u op de knop Toevoegen
klikken.
De gebruiker ziet dan het scherm voor de invoering van de opzoekingscriteria.
Wanneer u klikt op de knop "Opzoeken" verschijnt er een lijst met de dossiers die aan de
                                                                                         89

opzoekingscriteria beantwoorden. Deze lijst heeft volgend formaat: Dossiernr. Groep Type
Titel Intern nr.
Met de knop onderaan "Raadplegen" kunt u het geselecteerde dossier inkijken. In dit geval
moet een enkel dossier geselecteerd zijn. Om te koppelen, moet u een of meer dossiers in de
lijst selecteren en op de knop "Linken" klikken. Zo worden de dossiers gekoppeld. De
slaafdossiers hebben dezelfde titel, dito type, intern nummer als hun meesterdossier. Bij de
koppeling wordt het veld "Statistiek" van de slaafdossiers automatisch op "N" gezet. Die
kunnen, indien nodig, met de hand op "Y" worden geplaatst.

Statistieken
De knop Statistieken in het scherm Beheer dossier is alleen toegankelijk voor de gebruikers
van het "Algemeen Toezicht" bij wie de functie actief is. Hiermee wordt de "vlag" inzake
het
opnemen in de statistieken veranderd van Y in N of van N in Y. Standaard hebben de
automatische dossiers hun "vlag" "Statistieken" op N (nee) en de manuele dossiers op Y
(ja).
Het doel van deze functie is de verwaarloosbare vertragingen uit de statistieken te lichten.

Fusie dossiers
Deze functie is alleen toegankelijk voor het algemeen toezicht.
Deze actie is onomkeerbaar.
Onafhankelijke "originele" en "gedupliceerde" dossiers alsook meesterdossiers en hun
slaven
kunnen worden gefusioneerd.
In alle gevallen zijn gekoppelde dossiers "fysisch" gefusioneerd.
De slaafdossiers worden fysisch in de database gewist. Het meesterdossier wordt dan een
onafhankelijk dossier.
Fusioneren is enkel mogelijk als de betrokken dossiers gesloten zijn.
                                                                                           90




Besluit
Mijn stage was een aangename ervaring. De technische middelen voldeden ruimschoots om
mijn stageopdracht te voltooien.

Ook heb ik veel bijkomende kennis opgedaan, zowel praktische - als theoretische kennis. Ik
heb leren werken met het .NET platform. Ook heb ik mijn kennis van ASP aangevuld. Ik
heb leren werken in teamverband. In samenspraak met de collega’s zijn er altijd de beste
oplossingen gekozen voor de ontwikkeling van de toepassingen. Voor elk onderdeel was er
een deadline. Deze deadline werd telkens gerespecteerd.

Tijdens de ontwikkeling kwamen er problemen opdagen, maar dit had geen negatieve
invloed op de planning. Het resultaat is een programma die volledig voldoet aan de eisen
van de NDCC. Het Artweb onderdeel “beheer dossier” werd aanzienljk versneld.
           91




Bijlagen
                                                                                              92



1.        BRail WebControls Developers Guide

     S.N.C.B. / N.M.B.S.                                        CS IT 538
     CS.IT – Information Technology                             .NET Development Competence Centre

     Midi Atrium                                                    Sec 13/4
     Av. Porte de Hal / Hallepoort , 41-58                          02/52.83.471
     1060 Brussels                                                  johan.roosen@b-rail.be




                  IT538 - .NET Development Competence Centre


                         BRail WebControls Developers Guide


Author                             :   Laurent Nullens
Reference                          :
Filename                           :   WebControlsDevGuide.doc
Version                            :   1.0
Creation date                      :   20/01/2004
Modification date                  :   26/07/2012
Project Phase                      :




1.1       Distribution List

         NDCC                                Members of NDCC team




1.2       Version History

          Versio          Date         Short description of modifications
            n
           1.0        20/01/2004       Creation
                                                                                                  93

1.3   Audience
                   This article is intended for all the developers
                   using ASP.Net




1.4   Installation
      The Controls are provided as an “.msi” package installer file which can be found on the
      NDCC Server or soon downloaded from the NDCC Portal.
      The installation will perform the following tasks:
             - Install the assembly in the Gac
             - Install the assembly, the help file, … in a directory of your choice
             - Add an entry in the toolbox called “Brail.FRameWork’ containing the
                  controls
             - Add the assembly to the “add reference” window in visual studio. NET

1.5   Controls in the assembly
             BrailButton


      The BRailButton inherits all the functionalities of the classical asp.net Button. Nothing new
      has been added yet.



             BrailLabel


      The BRailLabel inherits all the functionalities of the classical asp.net Label. Nothing new has
      been added yet.



             BrailTextbox


      The BRailTextbox inherits all the functionalities of the classical asp.net Textbox. Two new
      properties have been added:

             -   Numeric box: true/false => enter only numerical text if selected
             -   TextAlignment: left/right => choose on which side the text will be
                 appearing when typing.



             BrailHyperlink


      The BRailHyperlink inherits all the functionalities of the classical asp.net Hyperlink.
      Nothing new has been added yet.
                                                                                          94

      BrailLinkButton


The BRailLinkButton inherits all the functionalities of the classical asp.net LinkButton.
Nothing new has been added yet.



      BrailDropDownList


The BRailDropDownList inherits all the functionalities of the classical asp.net
DropDownList. Nothing new has been added yet.



      BrailCheckbox


The BRailCheckBox inherits all the functionalities of the classical asp.net CheckBox.
Nothing new has been added yet.




      BrailListBox


The BRailListBox inherits all the functionalities of the classical asp.net ListBox. Nothing
new has been added yet.



      BrailRadioButton


The BRailRadioButton inherits all the functionalities of the classical asp.net RadioButton.
Nothing new has been added yet.



      BrailPanel


The BRailPanel inherits all the functionalities of the classical asp.net Panel. In addition
several properties have been added:

      -    Title: a title for the panel. The tile is situated on the upper left corner.

      -    TitleStyle: the style of the title (css for example)

      -    AllowClickOnTitle: hide the panel by clicking anywhere in the title and not
           on the link

      -    Canvas: state of the panel on load: visible/invisible

      -    Hidable: specify if the panel is hidable or not (normal panel).
                                                                                     95


      -   HidePanelImage: url of the image to display to hide the panel

      -   ShowPanelImage: url of the image to display to display the panel
      -
      -   HidePanelText: the text to display to hide the panel

      -   ShowPanelText: the text to displayt show the panel




      BrailDatePicker


The BRailDatePicker is an easy way to choose a date in a web page. It provides a textbox
with a button which displays a calendar. The chosen date is copied to the textbox and
verified against a regular expression. Here are the properties of the control:

      -   Autopostback: Whether a change in the control causes the form to be
          submitted

      -   CalendarStyle : The Style used by the calendar

      -   Columns: The number of columns shown in the date textbox

      -   DayHeaderStyle : The style used by the header of the calendar

      -   DayStyle : The style used to customize all days in the popup
          BRailDatePicker

      -   EnableClientScript: Enable script for client side if client support it
                                                                                             96

       -      OtherMonthDayStyle: The style used to customize days outside the current
              month in the popup BRailDatePicker

       -      SelectedDayStyle: The style applied to the currently selected date in the
              popup BRailDatePicker

       -      TitleStyle: The style applied to the title area of the popup BRailDatePicker

       -      TodayStyle: The style applied to the current day in the popup
              BRailDatePicker

       -      ReadOnly: specify whether the date textbox is read only

       -      SelectedDate: The currently selected date as a datetime variable

       -      SelectedDateText: The currently selected date in text format

       -      ValidationMessage: The error message shown when the entered text does
              not match the mm/dd/yyyy date format

       -      MouseOverColor: the color to be displayed around the cell when you pass
              over a cell of the calendar




You can retrieve the selected date by two ways:
      - you can react to the “datechanged” event
      - you can take the date from the “SelectedDate” property



       BRailCalendar


The BRailCalendar is a component which displays a calendar for a given month, week or
day. It displays the days with custom style and can display data coming from an xml file as a
dataset or xmldocument.


Properties:
                                                                                   97

-   DayFormat: FirstLetter, FirstTwoLetters, Full, Short =>The format of the
    day displayed in the header.
-   DayHeaderStyle: : The style used to customize the header of the calendar
-   NormalDayStyle: : The style used to customize day of the calendar
-   OtherMonthDayStyle: The style used to customize day from the other
    months
-   CurrentDayStyle: The style used to customize the current day in the
    calendar
-   TopicDayStyle : The style used to customize the day with events
-   TableStyle : The Style used to customize the Calendar
-   WeekEndStyle: The style used to customize the week-end day of the
    calendar
-   DataSource: XmlDocument or DataSet=>the source where the events for
    the calendar come from
-   TypeOfCalendar: day, week, month=> The type of calendar to be displayed
-   TypeOfCell:scrollable, full=> Whether to add or not scrollbar to a cell with
    too much events for its size (see screenshot).
                                                                                 98


In order to display event coming from a xml file, the xml must look like this:


        <?xml version="1.0" encoding="utf-8"?>
        <!--<Events
        xmlns="http://tempuri.org/CalendarSource.xsd">-
        ->
        <Events>
            <event>
                 <eventid>1</eventid>
                 <date>01/12/2003</date>
                 <description>first day</description>
                 <url>www.google.be</url>
                  </event>
            <event>
                <eventid>6</eventid>
                <date>31/12/2003</date>
                <description><![CDATA[ <img src="6.jpg"
        width="100%" border="0" /> ]]></description>
                <url>http://www.google.be</url>
                  </event>
         </Events>




How-to Bind data to the calendar:

with a dataset:
DtaSet ds=new DataSet();
ds.ReadXml(Server.MapPath("CalendarSource.xml"));
BRailCalendar1.DataSource=ds;
BRailCalendar1.DataBind();


with a XmlDocument:
XmlDocument xd=new XmlDocument();
xd.Load(Server.MapPath("CalendarSource.xml"));
BRailCalendar1.DataSource=xd;
BRailCalendar1.DataBind();
99
                                                                                               100


       BRailPopup


The BRailPopup is a components which displays a javascript alert.


Properties:
       - HandleEvent: displays the events that you can handle to show the alert
       - LinkedControl: displays the controls on which you can apply a popup
       - PopupText: The text that will be displayed in the popup



       BRailDataGrid


The BRailDataGrid inherits all the fonctionnalities from the classical asp.net datagrid.
Several modifications have been brought to make it more easy to use.


Properties:

       -      (Editable: true/false=> if true, display two columns: one with edit, update,
              cancel and one with delete. When yo use th is property you must )
       -      SortExpression: if AllowSorting==true, the grid is sorted with this
              expression. Multi columns sorting is ok. Ex: id asc, name desc . The syntax
              must always be like said before: column sortorder.
       -      SortFilter: if AllowSorting==true, the filter that will be applied to the data
              displayed in the grid. Ex: id>5
       -      MouseOverColor: the color that will be displayed when you pass over a
              row of the grid.
       -      AutomaticPaging: build the paging automatically, only works with
              RETRIEVEDATAFUNCTION
       -      AutomaticSorting: build the sorting automatically, only works with
              RETRIEVEDATAFUNCTION


Best practice to use the datagrid:

       1.     drop a datagrid on your page
       2.     create a function wich returns a datatable with the data you want to display
       3.     Add a function to the RetrieveDataFunction event of the datagrid
       4.     set the paging or the sorting as you want
       5.     all is done, the datagrid will refresh itself on page changing or sorting.


When sorting is enabled, there is a little symbol next to the name of the column which is
sorted which displays the sort of order(ASC/DESC). If you want to reset the sort, simply
click on “Reset Sorting”.


You can use the datagrid as a simple datagrid too.
                                                                                                101



2.        BRail Localization Developer’s guide

     S.N.C.B. / N.M.B.S.                                         CS IT 538
     CS.IT – Information Technology                              .NET Development Competence Centre

     Midi Atrium                                                      Sec 13/4
     Av. Porte de Hal / Hallepoort , 41-58                            02/52.83.471
     1060 Brussels
                                                                      johan.roosen@b-rail.be




                 IT538 - .NET Development Competence Centre

                         BRail Localization Developer’s guide


Author                             :   Laurent Nullens
Reference                          :
Filename                           :   LocalizationDevsGuide.doc
Version                            :   1.0
Creation date                      :   2/03/2004
Modification date                  :   26/07/2012
Project Phase                      :




2.1       Distribution List

         NDCC                                Members of NDCC team




2.2       Version History

          Versio          Date         Author        Short description of modifications
            n
           1.0         2/03/2004                     Creation
                                                                                                           102

    2.3   Audience
                            This article is intended for all the .Net
                            developers who want localization in their web
                            applications.



    2.4   Introduction
               Localization has always been a major problem for people creating web sites. So the .Net
               Framework comes with some classes to help developers. There are two namespaces called
               System.Globalization and System.Resources: Globalization has to do with
               internationalisation (currency, date format …) and Resources manages access to resource
               file. A resource file is a file containing some information that can be accessed via some
               classes of System.Resources. In the case of the localization there are two possibilities: we
               can store translations in satellite assemblies or resx files. But both of these solutions are not
               so easy to use. So with the Brail.Localization components we store the translations of web
               pages in plain xml file or, in the future in a database.
               At the time I write this paper, only localization through xml file is supported, so the
               explanations below will be based on xml file.

    2.5   Installation
               The assembly is provided as an “.msi” package installer file which can be found on the
               NDCC Server or soon downloaded from the NDCC Portal.
               The installation will perform the following tasks:
                      - Install the assembly in the Gac
                      - Install the assembly, the help file, … in a directory of your choice
                      - Add the assembly to the “add reference” window in visual studio. NET

    2.6   How-to use it

    2.6.1 Web.config

               First some parameters must be put in the web.config file:

                      -    ResourceBaseName: the name of the file containing the translations
                      -    ResourceManagerKey: Every control must have an extra attributes which is
                           and id between the xml file and the controls on the page. By default the
                           attribute is “key” but you can change it. DON’T FORGET to add the
                           “key=…” to each control on the page.
                      -    ResourceManagerType: XmlFile
                      -    ApplicationPath: the physical path of our web site.
                      -    ApplicationVariableName: The name that will be used for caching the
                           resourcemanager class.
                      -    SupportedCultures: a list of cultures that are supported by your application
                           separated by a “;”.


               Don’t forget to always put the configSections tags below in your web.config file or the
               LocalizedPage won’t be able to read the settings.


<configSections>
     <sectionGroup name="system.web">
          <section name="localizationsettings"
type="System.Configuration.NameValueFileSectionHandler, System,
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
     </sectionGroup>
                                                                                                          103

    2.6.2 Translation file

                After you must put an xml file containing the translation of your controls. This file is always
                put in the subdirectory “\bin\translation’ of the path you have specified in the web.config.
                The file must look like this:


<?xml version="1.0" encoding="utf-8"?>
<elements>
    <element name="Button1" type="System.Web.UI.WebControls.Button"
     test
form="TestXmlLocalization">
          <Text>
              <nl>dag</nl>
              <fr>bonjour</fr>
              <default>bonjour</default>
          </Text>
          <ToolTip>
              <nl> test dag</nl>
              <fr>test bonjour</fr>
              <default>test bonjour</default>
          </ToolTip>
    </element>
    <element name="BRailDropDownList1"
type="BRail.FrameWork.UI.WebControls.BRailDropDownList"
form="TestXmlLocalization">
          <Items>
              <nl><![CDATA[<?xml version="1.0" encoding="utf-16" ?>
                       <ArrayOfRLE xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                             <RLE T="een" V="1" />
                             <RLE T="twee" V="2" />
                       </ArrayOfRLE>"]]>
                       </nl>
              <fr><![CDATA[<?xml version="1.0" encoding="utf-16" ?>
                       <ArrayOfRLE xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                             <RLE T="un" V="1" />
                             <RLE T="deux" V="2" />
                       </ArrayOfRLE>]]>
                       </fr>
              <default><![CDATA["<?xml version="1.0" encoding="utf-16" ?>
                       <ArrayOfRLE xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                             <RLE T="un" V="1" />
                             <RLE T="deux" V="2" />
                       </ArrayOfRLE>]]>
                  </default>
          </Items>
    </element>
</elements>
                                                                                                   104



          Tag element:
                 - name : the key of the control
                 - type : the type of the control
                 - form: the form on which the control is situated


          Inside the tag Element, you put all the languages you want as a Tag. The language attribute
          must be the standard Culture Name (look in msdn for a complete list of cultures). Then,
          inside each language you put a tag corresponding to the name of the properties you want to
          be translated and the translation. As you can see it is possible to translate values of type
          collection (IT IS MANDATORY TO USE THE SYNTAX DESCRIBED IN THE
          EXAMPLE).

2.6.3 Using the component

          When the web.config has been modified and the xml file copied, you can call localization
          from you page. There are two methods:

                 Deriving from LocalizedPage


          Actually, when we create a web page, it automatically derives from the Page class. In our
          case, we simply change that and put LocalizedPage in place. That’s all, when you will reload
          the page it will automatically look up for translations.



                 Calling methods


          In the case you can’t derive from LocalizedPage it is still possible to use the component. You
          just have to call two methods:
                  - in the prerender you must call “LocalizedPage.localize”. This method will
                      go through every controls of the page and search for a translation.
                  - In the render you must call “LocalizedPage.RemoveKeyAttribute”.
                                                                                         105



ArrayList ac=null;
private void Page_Load(object sender, System.EventArgs e)
{
     //System.Threading.Thread.CurrentThread.CurrentCulture=new
System.Globalization.CultureInfo("fr");
     System.Threading.Thread.CurrentThread.CurrentUICulture=new
System.Globalization.CultureInfo("fr");
}
protected override void OnPreRender(EventArgs e)
{
     LocalizedPage.Localize(Page.Controls,ac);
     base.OnPreRender (e);
}
protected override void Render(HtmlTextWriter writer)
{
     LocalizedPage.RemoveKeyAttribute(ac);
     base.Render (writer);

}




                    With this code every controls are translated but it’s possible to only
                  retrieve a particular property
                    From a control:

//retrieve a property from a control
LocalizationElement le=Settings.CurrentManager.GetObject("Button1") as
              and search for a translation.
LocalizationElement;
le.GetStringProperty(Button1.GetType().ToString(),"Text");
                                                                                                106




3.        Exception Management Block - Developers Guide

     S.N.C.B. / N.M.B.S.                                          CS IT 538
     CS.IT – Information Technology                               .NET Development Competence Centre

     Midi Atrium                                                      Sec 13/4
     Av. Porte de Hal / Hallepoort , 41-58                            02/52.83.471
     1060 Brussels
                                                                      johan.roosen@b-rail.be




                  IT538 - .NET Development Competence Center

                Exception Management Block - Developers Guide


Author                             :   Johan Roosen
Reference                          :
Filename                           :   EMB developers guide.doc
Version                            :   1.0
Creation date                      :   15/01/2004
Modification date                  :   26/07/2012
Project Phase                      :




3.1       Distribution List

         NDCC                                Members of NDCC team




3.2       Version History

          Versio         Date          Author       Short description of modifications
            n
           1.0       15/01/2004 Johan               Creation
                                                                                                  107

3.3   Introduction
           The reader should already be familiar with exception handling practices and the exception
           handling in .NET. When and how to use exceptions is out of the scope of this manual.


           The BRail Exception Management Block (EMB) is based on two concepts:
                      Exception base class hierarchy
                      Exception Manager


           Although these two concepts are integrated in the same block, they can be used one without
           the other. This means that a developer can
                        use the Exception base classes and handle exceptions manually
                        use the .NET built-in exceptions and handle them by the Exception
                            Manager
                        use the Exception base classes and handle them by the Exception
                            Manager


           The EMB offers the functionality to automatically handle all exceptions in a consistent way
           and publish them easily to different destinations. These publications contain the basic .NET
           exception information, extended information (added by the BRail FrameWork) and if
           required extra information manually added by the developer.


           The namespaces used in the EMB are:
                      BRail.FrameWork.ExceptionManagement.Common
                      BRail.FrameWork.ExceptionManagement.Interfaces


           The assembly is strong-named and should be installed into the GAC.

3.4   Installation
           The EMB is provided as a “.msi” installer file which can be found on the NDCC Server or
           soon downloaded from the NDCC Portal. The installation is a straight forward process that
           doesn’t require much input from the user.


           The installation will perform the following tasks:
           Install assemblies into the GAC
                        Add a registry key
                           HKEY_LOCAL_MACHINE\Sotfware\Microsoft\.NET
                           Framework\BRail.FrameWork.ExceptionManagement.Common
                          Add entries to the Add Reference Tab “.NET”
                                                                                              108




3.5   Exception class hierarchy
           Every exception that you create should derive from the base class “BRailException”. This
           base class includes a lot more information about what went wrong, than the built-in .NET
           exceptions.

                 Protected void Button_Click (object Sender, EventArgs e)
                 {
                   BRailException newex = new BRailException (“Something went wrong”) ;
                 }



           Even if you catch a .NET exception (eg. FileNotFoundException) and you decide to rethrow
           the exception to the caller of your code, it is highly recommended that you create a new
           exception based on BRailException.
                 Try
                 {
                    …
                 }
                 Catch (DivideByZeroException ex)
                 {
                    BRailException newex1 = new BRailException (ex) ;
                    Throw (newex1) ;
                    // or
                    BRailException newex2 = new BRailException (“Incorrect division”,ex) ;
                    Throw (newex2) ;
                 }
                 Finally
                 {
                    …
                 }
                                                                                                     109

          This exception strategy should be clearly defined for each application. This will result in the
          creation of an application specific exception class hierarchy all derived directly or indirectly
          from BRailException.




                    Object

                         Exception


                          SystemException
                                                                            Provided by BRail FrameWork
                           ApplicationException
                                                                              Application specific

                                 BRailException


                                        Your Exception classes
                                         Your Exception classes
                                           Your Exception classes


3.6   Exception Manager
          The exception manager is responsible for publishing exceptions to a particular destination.
          The manager can publish the following exceptions:
                     .NET exceptions
                     Custom exceptions
                     BRailException
                     Custom exceptions derived from BRailException


          The publication destination can be configured in the application configuration file (eg
          web.config). This file is interpreted by a internal “Section Handler”. Based on this
          configuration a custom publisher component will be called to publish the exception. The
          BRail EMB contains already three publishers that can be used without any code effort:
                       Default Publisher (Event Viewer)
                       File Publisher
                       XML Publisher


          However it’s very easy to plug in your own exception handler. In the future the BRail EMB
          might also provide support for other commonly used providers.
                                                                                                110


3.7   Design
          The following image summarizes the structure of the EMB:




          The flow of logic when the Exception Management Application Block is used to publish an
          exception illustrated in the preceding diagram is as follows:
                        1. The application throws an exception, which can be derived from the
                             BaseApplicationException class provided in the Exception
                             Management Application Block.
                        2. The application calls the Publish method of the ExceptionManager
                             class.
                        3. The            ExceptionManager              class      uses         the
                             ExceptionManagerSectionHandler              class  to   retrieve   the
                             application’s exception management settings.
                        4. The exception management settings in the application’s configuration
                             file (if any) are read to determine how the exception should be
                             published.
                        5. If no settings are found, the exception is published in the Windows
                             Event Log by using the DefaultPublisher class. If the application has
                             exception management settings configured, the publishers listed in
                             the configuration file, which can include the DefaultPublisher class
                             and custom publisher classes, are used to publish the exception. All
                             publishers implement at least one of the interfaces defined in the
                             Interfaces assembly.
                        6. If an exception occurs while publishing through a custom publisher,
                             the exception manager raises a CustomPublisherException, and
                             uses the default publisher to publish it in the Windows Event Log.


          Mind that the exception manager doesn’t handle the exception itself, that has to be done by
          the application.
                                                                                                    111

3.8   Using the Exception Manager

3.8.1 Basic publishing

           The BRailException class doesn’t publish the exception by default. This decision is up to the
           application developer. Here is the code you should use:

                  include BRail.FrameWork.ExceptionManagement.Common ;
                  …
                  Try
                  {
                     …
                  }
                  Catch (DivideByZeroException ex)
                  {
                     BRailException newex = new BRailException (“Incorrect division”,ex) ;
                     ExceptionManager.Publish (newex) ;
                  }
                  Finally
                  {
                     …
                  }




3.8.2 Publishing additional information
           The ExceptionManager allows you to publish more information than included in the
           exception itself. This is done by providing a parameter of type NameValueCollection.


           Sample
                  include BRail.FrameWork.ExceptionManagement.Common ;
                  include System.Collections.Specialized;
                  …
                  Try
                  {
                     …
                  }
                  Catch (DivideByZeroException ex)
                  {
                     BRailException newex = new BRailException (“Incorrect division”,ex) ;
                     NameValueCollection extra = new NameValueCollection () ;
                     extra.Add ("NL","Deling door nul") ;
                     extra.Add ("FR","Divisé par zero") ;
                     ExceptionManager.Publish (newex , extra) ;
                  }
                  Finally
                  {
                     …
                  }




3.8.3 Switching on/off a publisher
           Published exceptions are sent to the Exception Manager. Based on configuration settings in
           the application configuration file, the manager decides which exception is published to which
           destination.
           The minimum settings in your configuration file should look like this:

                  <configSections>
                  <section
                  name="exceptionManagement"
                  type="BRail.FrameWork.ExceptionManagement.Common.ExceptionManagerSectionHandler
                  ,
                         BRail.FrameWork.ExceptionManagement.Common" />

                  </configSections>
                                                                                                   112


                  <exceptionManagement mode="on"/>



           The first part should never be modified by the developer.
           The <exceptionManagement> element is switched on and contains no publishers. This means
           that the default publisher (Event Viewer) is used. If the “mode” attribute is omitted the
           default is “on”.


           Switching the exceptionmanagement Off :

                  <exceptionManagement mode="off"/>




3.8.4 Using the Default Publisher
           The following sample is the default configuration:
                  <exceptionManagement mode="on">

                  <publisher
                  assembly="BRail.FrameWork.ExceptionManagement.Common"
                  type="BRail.FrameWork.ExceptionManagement.Common.DefaultPublisher" />

                  </exceptionManagement>



           Specify the event viewer category and source identifier:
                  <exceptionManagement mode="on">

                  <publisher
                  assembly="BRail.FrameWork.ExceptionManagement.Common"
                  type="BRail.FrameWork.ExceptionManagement.Common.DefaultPublisher"
                  logname="MyPersonalLog"
                  applicationname="MyPersonalSource" />

                  </exceptionManagement>




3.8.5 Using multiple publishers
           It is possible to publish an exception to multiple publishers at the same time. The supported
           publishers at this moment are Default (event viewer), File and XML.


           Sample:
                  <exceptionManagement mode="on">

                  <publisher
                                                                                                     113

                   assembly="BRail.FrameWork.ExceptionManagement.Common"
                   type="BRail.FrameWork.ExceptionManagement.Common.DefaultPublisher"
                   logname="MyPersonalLog"
                   applicationname="MyPersonalSource" />

                   <publisher
                   assembly="BRail.FrameWork.ExceptionManagement.Common"
                   type="BRail.FrameWork.ExceptionManagement.Common.FilePublisher"
                   filename="d:\dump.txt" />

                   <publisher
                   assembly="BRail.FrameWork.ExceptionManagement.Common"
                   type="BRail.FrameWork.ExceptionManagement.Common.XMLPublisher"
                   filename="d:\dump.xml"
                   exceptionFormat="xml" />

                   </exceptionManagement>


3.8.6 Filtering
            The built-in publishers and the custom once you create yourself are capable of filtering out
            exceptions based on their names:

                   <exceptionManagement mode="on">

                   <publisher
                   assembly="BRail.FrameWork.ExceptionManagement.Common"
                   type="BRail.FrameWork.ExceptionManagement.Common.DefaultPublisher"
                   include="*"
                   exclude="System.DivisionByZero" />

                   <publisher
                   assembly="BRail.FrameWork.ExceptionManagement.Common"
                   type="BRail.FrameWork.ExceptionManagement.Common.FilePublisher"
                   include ="*"
                   exclude="System.DivisionByZero;System.IO.FileNotFoundException"/>

                   <publisher
                   assembly="BRail.FrameWork.ExceptionManagement.Common"
                   type="BRail.FrameWork.ExceptionManagement.Common.XMLPublisher"
                   excptionFormat="xml"
                   include ="BRail.Mandahrin.Module.ParameterException"
                   exclude="*"/>

                   </exceptionManagement>




3.9   Best Practices
            As mentioned before best practices for creating, catching and throwing exceptions are out of
            the scope of this manual. However here are some important tips and rules that are highly
            recommended:
            Only catch an error if you want to take meaningful action.
                        Publishing
                        Recovering
                        Launching a compensation transaction
                        Cleaning up (releasing unmanaged resources, …)
                        Adding relevant information to the exception
            Exceptions are thrown by default to the calling component when they are not caught
            Avoid handling exceptions in back-end components. Otherwise the callers have no option to
            handle the exception the way they want.


            There are some articles available about exceptions that are very useful. You can find these on
            MSDN and some on the NDCC Library server.
                                                                                                         114

3.10 Useful technical information
          If an unexpected error occurs in the EMB code itself, EMB raises its own internal exception
          (and publishes them using the DefaultPublisher).




3.11 Using the config settings

          Without any configuration settings, ExceptionManager will publish using the Default
          publisher.



3.11.1    Publisher Elements Quick Reference:

                 mode
          If omitted, this attribute defaults to "on". Explicitly setting this attribute to "off" disables the
          publisher.

                 assembly
          The name of the assembly containing the publisher class. This is used to instantiate the
          publisher, and is therefore a mandatory attribute.

                 type
          This is the type name of the publisher class, and is used together with the assembly attribute
          to instantiate     the publisher. This attribute is mandatory.

                 exclude.
          This attribute is used to specify a semicolon delimited list of exception types that should not
          be published by this publisher. You can use the asterisk (*) wildcard character to exclude all
          exception types. Only the type of the outermost exception is evaluated.

                 include
          This attribute is used to force a particular exception type to be published, even if the exclude
          attribute is set to *.
                                                                                                   115

                exceptionFormat (only XMLPublisher)
         If this attribute is set to xml, then the exception is streamed to XML, and published using the
         publisher’s IExceptionXmlPublisher interface. Otherwise, the exception is published using
         the publisher's IExceptionPublisher interface.

                logname (only DefaultPublisher)
         Name used for creating a new category in the event viewer.

                applicationname (only DefaultPublisher)
         Identifier used as Source in the event viewer topics.

                Other custom attributes.
         You can add your own custom attributes, which are passed to your custom publishers by the
         ExceptionManager class. This allows developers to write custom logic in the publisher to
         examine these attributes and take appropriate action.




3.12 Future

3.12.1   Publishers
                        WMI Publisher
                        DataBase Log Publisher
                        OSD Publisher
                        Mail Publisher
                        MSMQ Publisher
         The mail publisher uses a .NET Mail component that is based on a COM component called
         Great-Mail2.dll. At this moment this assembly is not strong-named yet so it cannot be used
         by a strong-named publisher.

3.12.2   Event monitor
         This monitor will allow administrators to easily view exceptions published at any
         destination.

3.12.3   Code skeleton injections
         This feature will extend the VS.NET 2003 IDE with menu options that inject code skeletons
         directly into the code currently active file in the VS.NET code editor. Useful skeletons will
         be:
                      Event handling
                      Configuration file <exceptionManagement> and <publisher> examples
                      Quick start code for writing a custom publisher
                                                                                   116




Bibliografie
NMBS http://www.b-rail.be (20/04/2004) Algemene informatie.

Active Server Pages 2.0 Beginning Wrox Francis, Kauffman, Llibre, Sussman and Ullman
1998
Active ServeR Pages 2.0 proffessional Wrox Francis, Fedorov, Harrison, Homer, Murphy,
Sussman, Smith and Wood 1998

CR 444 Laison entre dossiers Christophe Waardenburg, Vincent Allard 2002

Referentiehandleiding ARTWEB versie 2.0.0b

Project G153/T4704X Functioneel analysedocument versie 1.0 12 Frix Luc / Erik Coopman
maart 2004

Project G153/T4704X SCOPE versie 1.1 Luc Frix maart 2004

IT538 - .NET Development Competence Center Setting up a development environment
versie 1.0 Vincent Allard 2003
IT538 - .NET Development Competence Center Naming Conventions versie 1.4 Johan
Roosen
IT538 - .NET Development Competence Center BRail WebControls Developers Guide
versie 1.0 Laurent Nullens maart 2004
IT538 - .NET Development Competence Center BRail Localization Developers guide versie
1.0 Laurent Nullens maart 2004
IT538 - .NET Development Competence Center Exception Management Block - Developers
Guide versie 1.0 Johan Roosen januari 2004

Admin A205i Handleiding Michel Staudinger maart 2004

MSDN Training Programming with the Microsoft .NET Framework Course number 2349b
MSDN Training Introduction to C# Programming Course number 2124b
MSDN Training Developing Microsoft ASP.NET Web Applications Using Visual Studio
.net Course Number 2310
MSDN Training Programming with Microsoft ADO.NET Course Number 2389B

								
To top