This post has been imported from the old blog and has not yet been converted to the new syntax yet.
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.



 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
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.



 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
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.

 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
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
 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
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.