Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
Another thing I had to do was a feasibility study on eID. This means I had to look into this technology, research what the possible uses are, if they can be implemented and how they have to be implemented.

The eID project is an initiative from the Belgium government, to replace the current passport of every citizen by an eID card. This is a smartcard which looks like the current Belgian passport, and contains certificates and identity data on its chip. Main functionalities of the eID card are data capture, authentication and digital signature.

Data capture is used in applications to read identity data from the card, such as name, address, gender and others. This gives an advantage to business applications which use this data, because it takes less time to enter the data, and no more typing errors can occur.

Authentication is done by using a certificate on the card. When the private key of the certificate is accessed, the eID middleware, provided by the government, will show a dialog asking for the PIN code of the card. Normally, only the owner of the cards knows this code, and can allow access to the private key. Authentication could be used on websites, physical locations, client-server applications and others.

A digital signature can be used to proof that some content originates from a certain user and has not been modify along the way. Possible uses are signing an email or a document. With eID, a digital signature has the same legal proof as a written one.



Every eID card contains an authentication and digital signature certificate, signed by the Citizen CA, which itself is signed by the Belgium Root CA.

When a citizen request and eID card at his municipality, it gets registered at the population registry, which requests a new certificate. After this a citizen can logon to a website, which will validate the certificate trough the OCSP protocol with the CA.

On the eID file system there are two main directories. One contains the specific user data in a proprietary format and the other one is PIN protected and contains the certificates.

Windows applications can use the Crypto API to access the certificates while everything else can use PKCS#11. There are also toolkits which hide the internal workings of the card.

A certificate always has to be validated, meaning the validity period has to be checked and the serial number of the certificate has to be checked with OCSP or against a CRL.
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
During my internship I had to test against different kinds of products, and to be sure everything worked on a clean install of this product, I had to create multiple virtual PC’s. One method of doing this was to create one clean Windows 2003 installation inside Virtual PC and copy this image to a new folder for every different server I needed. This was the method I started with, but one disadvantage was that it required a lot of disk space, as the base image already required 1.8 GB.

A solution to this problem was to use a feature of Virtual PC, called Differencing Disks. This allows for the creating of a base read-only image, which is called the parent, which can be shared with unlimited other virtual machines, the children.



Every child stores their disk changes in a separate file, making it possible to have one clean Windows 2003 parent image, and having a child which only adds Windows SharePoint Services to a separate file. The combination of parent and child would then become a Windows 2003 machine running Windows SharePoint Services.

This way, having a lot of different children uses a lot less space than having to copy the complete base image each time.

Additionally this method also can be used on a network to provide complete base images to all network clients. Making it possible to create an archive of base images for each platform (Windows 98, 2000, XP, 2003, Linux, BSD, …) and placing them on a read-only network share, ready to be consumed by all users creating their own local child disks.

 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.


On March 2, 2005 the ASP.NET 2.0 On Tour came to Belgium, Brussels. This is an international tour, all about the latest Microsoft technology, featuring speakers such as David Platt and Dave Webster.

The subjects of this event were about showing what ASP.NET 2.0 and Visual Studio 2005 had to offer, and how to migrate to these new products and technologies.

One of the sessions was about “Personalization & Membership in ASP.NET 2.0”, by Gunther Beersaerts and Bart De Smet, which was very nice thanks to the good balance between demos and slides.



They talked about the Membership Service, which takes care of the management of users, password generating, validating logins and everything else related to authentication. Other areas of ASP.NET 2.0 they touched were the Role Management Service and the Profile Service.

Trough the Role Management Service, everything related to authorization based on roles can be done in a simple way with static methods to perform key management tasks. While the Profile Service takes care of storing user-specific data persistently in a strongly typed manner, thus making it very easy to customize your site to the logged on user.

This event really gave a good view on what is to come in the web development area.
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
Blogs are a new communication medium, mainly used as a single-direction information channel. On a blog, the owner publishes new posts, which can be read and commented on by readers.

This model looks a lot like a forum where treads are started and replies are given, expect on a blog, only the blog owner creates new posts. Some compare this model to an online diary or the private newspaper of an amateur journalist.

The greatest strength of blogs is the fact that they are very personal and contain a lot of valuable information. They also show the human side of companies when employees are blogging.

Another great advantage of a blog is syndication. This is the use of a particular XML file, using a described schema, called an RSS-feed or an ATOM-feed, to display all the information on a particular blog. By using so called feed-readers, it is possible to read several blogs from one application.

As a part of my internship, I had to post articles about what I did on my blog. Most of these articles correspond with the content of this report.



 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
Another tool I had at my disposal was Microsoft Virtual PC. This is a product that enables you to run several operating systems inside your existing one, each one of them acting as a real PC.



This was very useful when I needed to test some of the things I created on a different server, a Windows 2003 server running Windows SharePoint Services for example.

After I had created my Windows 2003 image, I could use it on any PC I wanted to work on, on my laptop and on my desktop as well. This proved very useful when having to test against a specific machine.

A virtual PC can share its network with the host operating system, making it possible to run several virtual machines at one, simulating a complete network, acting as if it were unique servers on the network. This was a very nice feature before deploying something to the real production servers.



 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
For the Microsoft Student Council, I decided to write a small database application that would keep track of the users their points. The council has access to a SharePoint site, so I decided to create a WebPart that would use existing user data and integrate nicely into the existing infrastructure.



The first thing I did, was install the Web Part Templates for Visual Studio .NET on my machine. To do this, it required the Microsoft.SharePoint.dll during installation. So I decided to install Windows SharePoint Services first, which was freely available on the Microsoft Download website.

After I installed SharePoint, I discovered the SmartPart. This is a special WebPart, created by Jan Tielens and Fons Sonnemans, which allows you to encapsulate a regular ASP.NET User Control in a WebPart. This is a great solution because it gives you the productivity of using the designer and the power of accessing the SharePoint Object Model at the same time.

As this WebPart would be storing data, I had to start looking where to store it. My first idea was to store it right in the SharePoint database, but there was almost no information on it and I got advised it wasn’t a good thing to put third party data in the database. In the end I created two Custom Lists in SharePoint, who would act as database tables to store the data.



The next step was the creation of the User Control. To do this, references to Microsoft.SharePoint.dll and SmartPart.dll had to be added, the SmartPart, Microsoft.SharePoint and Microsoft.SharePoint.WebControls namespaces had to be imported and the IUserControl interface had to be implemented. This interface takes care of the link between your User Control and the SharePoint Web.

After this, it was possible to access everything of the SharePoint Object Model. For example, to fill a dropdown list with the available users, I used the following code:

[csharp]
private void FillUserList() {
this.viewUserList.Items.Clear();

SPUserCollection webUsers = this.SPWeb.Users;
this.viewUserList.Items.Add(new ListItem("All", "-1"));
foreach (SPUser webUser in webUsers) {
this.viewUserList.Items.Add(new ListItem(
Microsoft.SharePoint.Utilities.SPEncode.HtmlEncode(webUser.Name),
webUser.LoginName));
}
} /* FillUserList */
[/csharp]

This dropdown was later used as a filter in the administrative part of the WebPart.

To retrieve the available types from the Custom List, I used the following piece:

[csharp]
private void FillTypeList() {
this.typeList.Items.Clear();
SPListItemCollection puntenTypes = this.SPWeb.Lists["PuntenList"].Items;
foreach (SPListItem puntenType in puntenTypes) {
if (!Convert.ToBoolean(puntenType["Obsolete"].ToString())) {
this.typeList.Items.Add(new ListItem(
puntenType["Punten Type"].ToString(),
puntenType["Punten Type"].ToString()));
}
}
} /* FillTypeList */
[/csharp]

With code like these small pieces, demonstrating the SharePoint Object Model, I created a small User Control, containing a DataGrid to display the items, some input fields to add new items and a dropdown list with users, to filter on when being logged on as an Administrator.

 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
NSurvey already provides general charts displaying the results, but it uses a bar chart and I had to output pie charts as well. So, I implemented them as well.

First, I created a new page, called PieChartReport.aspx, which was empty. After this I used the same code as the BarChartReport and filled up a ChartPointCollection, which I then used to create a new PieChart, render it and send it back to the client

[csharp]
ChartEngine engine = new ChartEngine();
ChartCollection charts = new ChartCollection(engine);

engine.Size = new Size(350, 400);
engine.Charts = charts;
engine.Title = new ChartText();

if (questions.Questions[0].IsParentQuestionIdNull()) {
engine.Title.Text = Server.HtmlDecode(
Regex.Replace(questions.Questions[0].QuestionText, "<[^>]*>", " "));
} else {
String questionText = String.Format("{0} - {1}",
questions.Questions[0]["ParentQuestionText"].ToString(),
questions.Questions[0].QuestionText);
questionText = questionText.Replace(Environment.NewLine, "");
questionText = questionText.Replace("\t", "");
questionText = questionText.Replace("

", "");
questionText = questionText.Replace("

", "");
engine.Title.Text = Server.HtmlDecode(
Regex.Replace(questionText, "<[^>]*>", " "));
}

PieChart pie = new PieChart(data);
engine.Charts.Add(pie);
ChartLegend legend = new ChartLegend();
legend.Position = LegendPosition.Bottom;
engine.HasChartLegend = true;
engine.Legend = legend;
engine.GridLines = GridLines.None;
[/csharp]



Update: I used the following control by the way (which was already in NSurvey): http://www.carlosag.net/Tools/WebChart/Default.aspx
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
NSurvey provides charting reporting by default, but this could be enhanced by using the Country List control together with the added Belgian Regions. With this question in a survey, as a required question, every entry would have location information. Together with MapPoint a graphical overview could be made, showing additional information per country and region.

To accomplish this, I created a new administration page and edited the UINavigator and HeaderControl classes to add the new page to the menu. On this page were two dropdown lists which included the column names of a survey’s text entries. These lists were used to indicate where NSurvey stored the Country and Region questions. Together with a button that would generate the chart.



To generate the chart, all possible regions were first collected by grouping the entries and storing the unique country and regions. After this, the MapPoint FindService was instantiated and the Find method was called for each address.

[csharp]
FindServiceSoap findService = new FindServiceSoap();
if (ConfigurationSettings.AppSettings["MapPointProxy"] != String.Empty) {
findService.Proxy = this.proxyObject;
}
findService.Credentials = this.ourCredentials;
findService.PreAuthenticate = true;

FindSpecification findSpec = new FindSpecification();
findSpec.DataSourceName = "MapPoint.EU";

foreach (DictionaryEntry locationEntry in locationData) {
// key example: "West-Vlaanderen, BE"
findSpec.InputPlace = locationEntry.Key.ToString();
FindResults foundResults = findService.Find(findSpec);
if (foundResults.NumberFound > 0) {
((CustomLocation)locationEntry.Value).LatLong =
foundResults.Results[0].FoundLocation.LatLong;
}
}
[/csharp]

This gave me the LatLong of every location MapPoint had found, which I used to create an array of Location objects to be passed to the GetBestMapView method. This method returned a MapViewRepresentations object which described to view to use when calling the GetMap method. This view assured every location was on it.

[csharp]
MapViewRepresentations mapRepresentations =
renderService.GetBestMapView(myLocations, "MapPoint.EU");
ViewByHeightWidth[] myViews = new ViewByHeightWidth[1];
myViews[0] = mapRepresentations.ByHeightWidth;
[/csharp]

At this point all required location information was known, the only thing left was to define pushpins that would show up on the generated map and would be clickable.

[csharp]
Pushpin[] myPushpins = new Pushpin[foundRegions.Count];
Int32 pinCounter = 0;
foreach (DictionaryEntry foundRegion in foundRegions) {
myPushpins[pinCounter] = new Pushpin();
myPushpins[pinCounter].IconDataSource = "MapPoint.Icons";
myPushpins[pinCounter].IconName = "1"; // Red pin
Int32 nrResults = ((CustomLocation)foundRegion.Value).ResultCount;
myPushpins[pinCounter].Label = String.Format("{0} {1}",
nrResults,
(nrResults == 1) ? "result" : "results");
myPushpins[pinCounter].LatLong = (LatLong)foundRegion.Key;
myPushpins[pinCounter].ReturnsHotArea = true;
myPushpins[pinCounter].PinID =
(CustomLocation)foundRegion.Value).Location();
pinCounter++;
}
[/csharp]

To get the map, I had to call the GetMap method and supply a MapSpecification. This specification describes the size of the map, the quality, the pushpins and what MapPoint should return. Here, it will return a URL, pointing to the generated map.

[csharp]
MapSpecification mapSpec = new MapSpecification();
mapSpec.DataSourceName = "MapPoint.EU";
mapSpec.Views = myViews;
mapSpec.Options = new MapOptions();
mapSpec.Options.ReturnType = MapReturnType.ReturnUrl;
mapSpec.Options.Format = new ImageFormat();
mapSpec.Options.Format.Height = 500;
mapSpec.Options.Format.Width = 500;
mapSpec.Options.Style = MapStyle.Locator;
mapSpec.Pushpins = myPushpins;
MapImage[] mapImages = renderService.GetMap(mapSpec);
[/csharp]

After the call, MapPoint returned a MapImage object, containg the url to the map, together with information about the special areas on the map, called HotAreas. To make these areas clickable on the map, an HTML imagemap had to be generated.

[csharp]
StringBuilder imageMapName = new StringBuilder();
imageMapName.Append("imageMapName.Append("_Map\">");
for (Int32 i = 0; i < hotAreas.Length; i++) {
String pinId = hotAreas[i].PinID;
imageMapName.Append("\n imageMapName.Append(hotAreas[i].IconRectangle.Left).Append(",");
imageMapName.Append(hotAreas[i].IconRectangle.Top).Append(",");
imageMapName.Append(hotAreas[i].IconRectangle.Right).Append(",");
imageMapName.Append(hotAreas[i].IconRectangle.Bottom);
imageMapName.Append("\" title=\"").Append(pinId).Append("\">");
}
imageMapName.Append("
");
this.imageMapHotAreas.Text = imageMapName.ToString();
mapObject.Attributes["USEMAP"] = "#" + mapObject.ID + "_Map";
[/csharp]

The result was a map, scaled to the best size to include all locations, with pushpins on it, which are clickable and point to the same page with an additional querystring.



This made it possible to visualize the results per region, and when you select a certain region, provide filtered results of that region.
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
One of the standard controls of NSurvey is the Country List, which provides a dropdown list of countries. Belgium is one of these countries, but when you select Belgium, it doesn’t display the possible regions for Belgium.

This is because the region information is also implemented with the subscriber model. When the country selection changes, it publishes the selected country to the Region List which then looks up the xml file of the selected country, containing the region information. The problem was that there wasn’t a region file for Belgium. So, I looked up the Belgian regions from Microsoft Passport and created the be.xml file:

[xml]



Region :



[Select Region]


Antwerpen
Antwerpen


Vlaams-Brabant
Vlaams-Brabant


Hainaut
Hainaut


Liege
Liege


Limburg
Limburg


Luxembourg
Luxembourg


Namur
Namur


Oost-Vlaanderen
Oost-Vlaanderen


Waals-Brabant
Waals-Brabant


West-Vlaanderen
West-Vlaanderen




[/xml]
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
As this application was going to collect feedback from Microsoft events, it had to look like it belonged to Microsoft, and it had to be designed professionally. To do this, I visited the Microsoft site, and saved the page to my dev pc. There I stripped all the content and created a template with two user controls, SiteHeader and SiteFooter.

The next step was to include the previously created SurveyListControlOverview on the Default.aspx page to provide a starting point for the user.



When they user selected a survey and clicked the button, the OverviewSurveyId property was retrieved and forwarded to the Survey.aspx page, which displayed the survey in the same layout, together with the survey title.



If an error occurs, the user gets redirected to a generic error page and an email gets dispatched to the site administrators.



A contact page was also added to provide a contact person for users having problems or questions.



The last step in creating the layout was testing if it worked the same in Internet Explorer and Mozilla Firefox. Luckily it worked the same from the first time and the layout was finished.
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
By default NSurvey provides different kinds of answer types. These are for example Basic Field, Rich Field, Calendar Field, Email Field, Hidden Field, Password Field, Large Field and dropdown lists which use XML files as data source. NSurvey, however, also allows you to extend on these types to create new answer types, with specific functionality.

One of the requirements of the survey was that it had to be possible for students to select their school from a list, but also have the possibility to enter it manually if it wasn’t listed. To do this, I created a School answer type.

This type was inherited from a regular Basic Field type, but was invisible by default. The special feature of this field was that it subscribed to a dropdown list which listed all available schools and an Other possibility. This meant that when the selection of the dropdown list changed, it would publish the new selection to all subscribed answers. Because of this, when the Other possibility was chosen, the field was made visible and it was possible to manually enter the school.

To do this, I had to implement the IAnswerSubscriber interface and use the following code for the ProcessPublishedAnswers method:

[csharp]
public void PublisherCreation(Object sender, AnswerItemEventArgs e) { }

public void ProcessPublishedAnswers(Object sender, AnswerItemEventArgs e) {
if (e != null && e.PostedAnswers != null && e.PostedAnswers.Count > 0) {
String selectedSchool = ((PostedAnswerData)e.PostedAnswers[0]).FieldText;
this.ShowField = selectedSchool.ToLower().Equals("other");
this.CreateChildControls();
}
} /* ProcessPublishedAnswers */
[/csharp]

I also provided a modified CreateChildControls method:

[csharp]
protected override void CreateChildControls() {
if (this.ShowField) {
if (this.ShowAnswerText) {
// This prevents the Answer title being displayed twice
if (Controls.Count > 2) {
Controls.RemoveAt(1);
Controls.RemoveAt(0);
}

if (this.ImageUrl != null && this.ImageUrl.Length != 0) {
Image selectionImage = new Image();
selectionImage.ImageUrl = this.ImageUrl;
selectionImage.ImageAlign = ImageAlign.Middle;
selectionImage.ToolTip = Text;
Controls.AddAt(0, selectionImage);
} else {
Literal literalText = new Literal();
literalText.Text = this.Text;
Controls.AddAt(0, literalText);
}

Controls.AddAt(1, new LiteralControl("
"));
}

if (this.FieldHeight > 1) {
// Creates a multi line field
_fieldTextBox.TextMode = TextBoxMode.MultiLine;
_fieldTextBox.Wrap = true;
_fieldTextBox.Columns = this.FieldWidth;
_fieldTextBox.Rows = this.FieldHeight;
} else {
_fieldTextBox.MaxLength = this.FieldLength;
_fieldTextBox.Columns = this.FieldWidth;
}

Controls.Add(_fieldTextBox);
OnAnswerPublisherCreated(new AnswerItemEventArgs(GetUserAnswers()));
} else {
Controls.Clear();
}
} /* CreateChildControls */
[/csharp]

This way, the field only got shown when the published answer equaled other, otherwise it was hidden. Another version of this was the CheckBoxField answer type. This type provided a default invisible field, which became visible after a certain checkbox was checked.



 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
NSurvey supports matrix questions in its surveys. The only problem with this type of question was that in the reporting section of NSurvey, it listed each row of a matrix question as a possible selection, but it didn’t include which matrix it belonged to. This leaded to a very confusing list, when you have several identical matrix questions which only differentiated in the main question asked.

The solution I had in mind was to change the output from “row question” to “matrix question – row question”. To do this, I first had to modify some stored procedures to include the ParentQuestionText field. After this I traced down the places where the possible questions were added to the dropdown list and added some logic to check if it was a matrix question and concatenated the matrix question with the row question.

One of the places where I had to do this was in the BarChartReport class, which was responsible for generating charts of the rated matrix questions. In the SetQuestionData method the following piece of code could be found

[csharp]
engine.Title.Text = Server.HtmlDecode(
Regex.Replace(_dataSource.Questions[0].QuestionText, "<[^>]*>", " "));
[/csharp]

Which I changed to the following:

[csharp]
if (_dataSource.Questions[0].IsParentQuestionIdNull()) {
engine.Title.Text = Server.HtmlDecode(
Regex.Replace(_dataSource.Questions[0].QuestionText, "<[^>]*>", " "));
} else {
String questionText = String.Format("{0} - {1}",
_dataSource.Questions[0]["ParentQuestionText"].ToString(),
_dataSource.Questions[0].QuestionText);
questionText = questionText.Replace(Environment.NewLine, "");
questionText = questionText.Replace("\t", "");
questionText = questionText.Replace("

", "");
questionText = questionText.Replace("

", "");
engine.Title.Text = Server.HtmlDecode(
Regex.Replace(questionText, "<[^>]*>", " "));
}
[/csharp]

This change, together with the changed procedure because the ParentQuestionText had to be used, resulted in charts with the correct title.



The only thing left was to make sure this change also occurred in the HTML report and the questions dropdown list.

To do this I had to add the following piece of code to the GetQuestionListWithSelectableAnswers method in the DataAccess part:

[csharp]
foreach (QuestionData.QuestionsRow row in questions.Questions) {
if (!row.IsParentQuestionIdNull()) {
row.QuestionText = String.Format("{0} - {1}",
row["ParentQuestionText"].ToString(),
row.QuestionText);
}
}
[/csharp]

These changes made the matrix questions display correctly, as you can see in this picture, which represents a five-question matrix.

 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
The first thing I noticed is the small dropdown in the admin section listing all available surveys. This would become my starting point for users, a perfect place to choose the survey they want to take.

I tracked this down to the SurveyListControl user control which I inherited to create SurveyListControlOverview. This user control removes to automatic postback when it’s in overview mode and also provides an OverviewSurveyId property to indicate the selected survey. It also displays all surveys, because it had to run in anonymous mode, without users having to log on before being able to answer. A shared password would be provided on the event, giving access to the survey.

After this, the user could select a survey from the dropdown list. The only problem was that the choices were ordered by creation date, which would become a problem in the long run when a lot of surveys would be available. To change this I added a simple ORDER BY Title in the vts_spSurveyGetList stored procedure.

At this point, I had a dropdown list with all surveys listed alphabetically to add to any aspx page I wanted.

 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
For one of the projects I had to do, I had to create an online survey application, which would be used to gather feedback from Microsoft events. Up until then, feedback was collected by handing out a form and entering the data manually.

As I was given free choice on how to solve this problem I suggested using an existing open-source framework and extending it to meet the requirements. This suggestion was quickly approved because on one side it meant commitment from Microsoft towards open-source and on the other hand it prevented re-inventing the wheel. The project used for this solution is called NSurvey. This provides a survey framework, making it very easy to setup surveys, add questions, add users, do mailings, implement security on a survey-based level, perform statistical operations on the answers and add new functionality by extending on existing classes.



NSurvey is an ASP.NET application, written in C#, which uses a SQL Server back-end, using stored procedures, and various other layers. The installation of NSurvey went very smoothly because of an msi file, placing all files in their correct location.

I started by testing the application and learning the big structure of how it worked. During this small test round, I began thinking on how the final solution would look.
 
Deze post is geïmporteerd van de oude blog en is nog niet geconverteerd naar de nieuwe syntax.
One of the tools I had in my toolbox was Reflector. This tool is written by Lutz Roeder and allows you to examine a .NET assembly. Through the use of reflection it can display all namespaces, classes, methods, properties, events and fields in the dll.

It is possible to view the code in IL, C#, VB.NET and Delphi. Some of the useful features are the Call and Callee Graph.

The Call Graph shows you which items are used by a given method, while the Callee Graph displays all the methods that call a given method.







Forgot something for blog readers, the url where to get it: http://www.aisto.com/roeder/dotnet/