DotNetNuke: Simple Survey (page 2)

[Back to: Simple Survey Page 1]

Display Questions

The survey uses the DynamicControlsPlaceholder control by Denis Baur to allow ViewState to be maintained for the dynamically created Survey controls.

The DisplaySurvey method dynamically creates the table used to hold the Survey:

        #region DisplaySurvey
        private void DisplaySurvey()
        {
            // Add elements to the DCP panel

            // Create Table
            Table objTable = new Table();
            // Add the Table to DCP panel
            DCP.Controls.Add(objTable);
            objTable.ID = "ResultsTable";

            SimpleSurveyDataContext SimpleSurveyDataContext = new SimpleSurveyDataContext();

            var SurveyQuestions = from SurveyDataItems in SimpleSurveyDataContext.SurveyDataItems
                                  where SurveyDataItems.ModuleID == ModuleId
                                  where SurveyDataItems.Visible == true
                                  orderby SurveyDataItems.SortOrder
                                  select SurveyDataItems;

            foreach (var SurveyQuestion in SurveyQuestions)
            {
                TableRow objTableRow = new TableRow();
                TableCell QuestionCell = new TableCell();
                TableCell AnswerCell = new TableCell();
                objTableRow.Cells.Add(QuestionCell);
                objTableRow.Cells.Add(AnswerCell);
                objTable.Rows.Add(objTableRow);

                // Display Question
                string strRequired = (SurveyQuestion.Required == true) ? "<font color='#cc0000'>*</font>" : "";
                string strMoney = (SurveyQuestion.Type == "Money") ? "$" : "";
                Label objLabel = new Label();
                QuestionCell.Controls.Add(objLabel);
                QuestionCell.Style.Add(HtmlTextWriterStyle.TextAlign, "right");
                objLabel.Text = String.Format("{0}{1}:{2}", strRequired, SurveyQuestion.DataName, strMoney);

                // Display Answer Form Element
                AnswerFormElement(AnswerCell, SurveyQuestion.Type, SurveyQuestion.SurveyDataItemID.ToString());

                // Create ID's for controls so they will be persisted in ViewState
                objTableRow.ID = String.Format("{0}", SurveyQuestion.SurveyDataItemID.ToString());
                QuestionCell.ID = String.Format("{0}_QuestionCell", SurveyQuestion.SurveyDataItemID.ToString());
                AnswerCell.ID = String.Format("{0}_AnswerCell", SurveyQuestion.SurveyDataItemID.ToString());
                objLabel.ID = String.Format("{0}_QuestionLabel", SurveyQuestion.SurveyDataItemID.ToString());
            }   
            
            ltValidation.Text = "<br /><i>(Items marked <font color='#cc0000'>*</font> are required)</i><br />";
        }
        #endregion

The AnswerFormElement method determines the proper control to use to gather each answer and adds it to the control collection. Note that the FileUpload control is used to allow images to be uploaded.

        #region AnswerFormElement
        private void AnswerFormElement(TableCell QuestionCell, string SurveyQuestionType, string strSurveyDataItemID)
        {
            switch (SurveyQuestionType)
            {
                case "Text":
                    TextBox objLargeTextBox = new TextBox();
                    QuestionCell.Controls.Add(objLargeTextBox);
                    objLargeTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objLargeTextBox.TextMode = TextBoxMode.MultiLine;
                    objLargeTextBox.Columns = 25;
                    objLargeTextBox.Rows = 2;
                    objLargeTextBox.MaxLength = 200;
                    break;
                case "Dropdown":
                    DropDownList objDropDownList = new DropDownList();
                    QuestionCell.Controls.Add(objDropDownList);
                    objDropDownList.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objDropDownList.Items.AddRange(AddListItems(Convert.ToInt32(strSurveyDataItemID)));
                    break;
                case "Radio Buttons":
                    RadioButtonList objRadioButtonList = new RadioButtonList();
                    QuestionCell.Controls.Add(objRadioButtonList);
                    objRadioButtonList.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objRadioButtonList.Items.AddRange(AddListItems(Convert.ToInt32(strSurveyDataItemID)));
                    break;
                case "Check Boxes":
                    CheckBoxList objCheckBoxList = new CheckBoxList();
                    QuestionCell.Controls.Add(objCheckBoxList);
                    objCheckBoxList.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objCheckBoxList.Items.AddRange(AddListItems(Convert.ToInt32(strSurveyDataItemID)));
                    break;
                case "Integer":
                    TextBox objIntegerTextBox = new TextBox();
                    QuestionCell.Controls.Add(objIntegerTextBox);
                    objIntegerTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objIntegerTextBox.Columns = 4;
                    break;
                case "Double":
                    TextBox objDoubleTextBox = new TextBox();
                    QuestionCell.Controls.Add(objDoubleTextBox);
                    objDoubleTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objDoubleTextBox.Columns = 4;
                    break;
                case "Money":
                    TextBox objMoneyTextBox = new TextBox();
                    QuestionCell.Controls.Add(objMoneyTextBox);
                    objMoneyTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objMoneyTextBox.Columns = 4;
                    break;
                case "Email":
                    TextBox objEmailTextBox = new TextBox();
                    QuestionCell.Controls.Add(objEmailTextBox);
                    objEmailTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objEmailTextBox.Columns = 35;
                    break;
                case "Date":
                    TextBox objDateTextBox = new TextBox();
                    QuestionCell.Controls.Add(objDateTextBox);
                    objDateTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objDateTextBox.Columns = 10;
                    break;
                case "Website":
                    TextBox objWebsiteTextBox = new TextBox();
                    QuestionCell.Controls.Add(objWebsiteTextBox);
                    objWebsiteTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    objWebsiteTextBox.Columns = 35;
                    break;
                case "Image":
                    FileUpload objUploadTextBox = new FileUpload();
                    QuestionCell.Controls.Add(objUploadTextBox);
                    objUploadTextBox.ID = String.Format("{0}_Answer", strSurveyDataItemID);
                    break;
            }
        }
        #endregion

When an entry is submitted, the following methods are run to perform validation, upload any images, and if there are no errors, save the data:

            // Validate Required Fields
            colValidationList = ValidateRequiredFields(colCompleteSurveyItems);
            if (colValidationList.Count > 0)
            {
                DisplayValidationErrors(colValidationList);
                return;
            }

            // Validate Field Types
            colValidationList = ValidateFieldValues(colCompleteSurveyItems);
            if (colValidationList.Count > 0)
            {
                DisplayValidationErrors(colValidationList);
                return;
            }

            // Upload any images
            bool boolUploadComplete = UploadImages(colCompleteSurveyItems);
            if (!boolUploadComplete)
            {
                colValidationList.Add("There was an error uploading a image file.");
                colValidationList.Add("Only .jpg/.jpeg/.gif allowed.");
                DisplayValidationErrors(colValidationList);
                return;
            }

            // Save data
            SaveSurveyItems(colCompleteSurveyItems);
            DisplaySurveyValues();

The following code saves the responses to the database:

        #region SaveSurveyItems
        private void SaveSurveyItems(List<SurveyItem> colCompleteSurveyItems)
        {
            SimpleSurveyDataContext SimpleSurveyDataContext = new SimpleSurveyDataContext();

            // Get all current items
            var CurrentDataAnswers = from SurveyDataAnswers in SimpleSurveyDataContext.SurveyDataAnswers
                                     from SurveyDataItems in SimpleSurveyDataContext.SurveyDataItems
                                     where SurveyDataAnswers.SurveyDataItemID == SurveyDataItems.SurveyDataItemID
                                     where SurveyDataItems.ModuleID == ModuleId
                                     where SurveyDataAnswers.UserID == UserId
                                     select SurveyDataAnswers;

            // Delete all current Items
            SimpleSurveyDataContext.SurveyDataAnswers.DeleteAllOnSubmit(CurrentDataAnswers);
            SimpleSurveyDataContext.SubmitChanges();

            // Add all new items
            foreach (var SurveyItem in colCompleteSurveyItems)
            {
                if (SurveyItem.ItemTypeName != "CheckBoxList")
                {
                    SurveyDataAnswer objSurveyDataAnswer = new SurveyDataAnswer();
                    objSurveyDataAnswer.UserID = UserId;
                    objSurveyDataAnswer.SurveyDataItemID = SurveyItem.SurveyDataItemID;
                    objSurveyDataAnswer.Value = SurveyItem.ItemValue;

                    SimpleSurveyDataContext.SurveyDataAnswers.InsertOnSubmit(objSurveyDataAnswer);
                    SimpleSurveyDataContext.SubmitChanges();
                }
                else
                {
                    // For Check boxes, multiple rows are saved
                    char[] delimiterChars = { ',' };
                    string[] SurveyValues = SurveyItem.ItemValue.Split(delimiterChars);

                    foreach (string SurveyValue in SurveyValues)
                    {
                        SurveyDataAnswer objSurveyDataAnswer = new SurveyDataAnswer();
                        objSurveyDataAnswer.UserID = UserId;
                        objSurveyDataAnswer.SurveyDataItemID = SurveyItem.SurveyDataItemID;
                        objSurveyDataAnswer.Value = SurveyValue;

                        SimpleSurveyDataContext.SurveyDataAnswers.InsertOnSubmit(objSurveyDataAnswer);
                        SimpleSurveyDataContext.SubmitChanges();
                    }
                }
            }
        }
        #endregion

Survey Results

A single Linq to SQL query is all that is needed to display the results for Dropdowns, Radio Buttons, and Check Boxes:

        #region DisplaySurveyResults
        private void DisplaySurveyResults()
        {
            SimpleSurveyDataContext SimpleSurveyDataContext = new SimpleSurveyDataContext();

            var results = from SurveyDataItems in SimpleSurveyDataContext.SurveyDataItems
                          from SurveyDataAnswers in SimpleSurveyDataContext.SurveyDataAnswers
                          where SurveyDataItems.SurveyDataItemID == SurveyDataAnswers.SurveyDataItemID
                          where SurveyDataItems.ModuleID == ModuleId
                          where SurveyDataItems.Visible == true
                          where (SurveyDataItems.Type == "Dropdown" || SurveyDataItems.Type == "Radio Buttons" || SurveyDataItems.Type == "Check Boxes")
                          group SurveyDataItems by SurveyDataItems.SurveyDataItemID into Questions
                          select new
                          {
                              Question = SimpleSurveyDataContext.SurveyDataItems.Where(x => x.SurveyDataItemID == Convert.ToInt32(Questions.Key)).FirstOrDefault().DataName,
                              Options = from SurveyDataAnswers in SimpleSurveyDataContext.SurveyDataAnswers
                                        where SurveyDataAnswers.SurveyDataItemID == Questions.Key
                                        where SurveyDataAnswers.Value != ""
                                        group SurveyDataAnswers by SurveyDataAnswers.Value into SurveyOptions
                                        select new
                                        {
                                            Option = SurveyOptions.Key,
                                            Count = SurveyOptions.Count().ToString()
                                        },
                              Count = Questions.Count().ToString()
                          };

            lvResults.DataSource = results;
            lvResults.DataBind();
        } 
        #endregion

The administrator survey results also requires only one Linq to SQL query:

        #region LoadUserResults
        private void LoadUserResults()
        {
            if (ddlUser.Items.Count > 0)
            {
                SimpleSurveyDataContext SimpleSurveyDataContext = new SimpleSurveyDataContext();

                var results = from SurveyDataItems in SimpleSurveyDataContext.SurveyDataItems
                              from SurveyDataAnswers in SimpleSurveyDataContext.SurveyDataAnswers
                              where SurveyDataItems.SurveyDataItemID == SurveyDataAnswers.SurveyDataItemID
                              where SurveyDataItems.ModuleID == ModuleId
                              where SurveyDataAnswers.UserID == Convert.ToInt32(ddlUser.SelectedValue)
                              orderby SurveyDataItems.SortOrder
                              select new
                              {
                                  Question = SurveyDataItems.DataName,
                                  Answer = SurveyDataAnswers.Value
                              };

                if (results.Count() > 0)
                {
                    gvAnswers.DataSource = results;
                    gvAnswers.DataBind();
                }
            }
        }
        #endregion

A Simple Survey

This module allows an administrator to create a form that can capture all the standard HTML form types including file upload. While it can provide basic form input functionality, it is designed to tabulate responses.

Primarily this module is intended to provide an example of using Linq to Objects, and Linq to SQL to greatly reduce the amount of code that would be otherwise required.

 

 


Buy DotNetNuke Modules from Snowcovered

 DotNetNuke Powered!DotNetNuke is a registered trademark of DotNetNuke Corporation.