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



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

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