Several months ago I wrote a multiple choice exam application using the WebForms framework. The idea revolved around displaying questions and choices to the user and giving them the ability to select the correct answer. Although the idea was simple but the limited control over the HTML markup made it difficult to implement. In this article we are going to show how easy it is to implement the multiple choice exam application using ASP.NET MVC Framework.

Scenario:

The application allows the user to take a multiple choice exam. This article only focuses on creating the exam where having a single correct answer. In the future articles we will focus on how to extend this feature to include multiple correct answers. The application does not use any database. The exam, questions and choices are all stored in the memory.

Creating Entities:

The first task is to create entities which will be used in our application. The application uses three entities namely Exam, Question and Choice. The class diagram for the entities is shown below:


Creating an Exam:

In real life application your exam will be stored in the database. To make things simpler we are going to store our exam in memory. The ExamService is responsible for creating the exam for the user. The implementation is shown below:



As, you can see in the above code we have created a simple dummy exam. The above implementation highlights some of the important points about the structure of the entities. The OrderNumber field in the Question entity can be used for multiple purposes. In this application it serves the purpose of assigning different groups to the choices as we will see later in the article. It can also be used to dictate the ordering of the questions displayed to the user. This is really helpful if a question has a dependency on the previous question.  

The IsAnswer field in the Choice entity represents if the choice is the correct answer. Since, in our application we can only have one correct answer per question it is only set to true for a single choice per question.

Displaying the Exam to the User:

The next step is to display the exam to the user. There are many different ways of accomplishing this task. We are going to make things a little cleaner by separating the Question and the Choice as partial views. First let's take a look a the Publish.aspx page which is responsible for displaying the exam to the user. The first thing to notice about Publish.aspx page is that it is strongly type view page as shown in the code below:



By making it strongly type we are saying that this page is exclusively created to interact with the Exam object. This also means that we can access the nested objects inside the Exam object which are Question and Choice.  

Here is the complete implementation of the Publish.aspx page:



The hidden field is used to submit the Id of the exam. This will help us to identify the exam. The form action is setup to fire the "Grade" action which is responsible for grading the exam. In order to display the questions we loop through the exam questions and render the "__question" partial view. You can write HTML code instead of using the partial view but by using partial view we are separating the structure of the questions into a separate place. Each question is also passed to the "__question" partial view which acts as the Model for that view.

Let's move to the partial view and check out its implementation. Once again the first thing to note about the "__question" partial view is that it is strongly typed.



This gives us complete control over the Question object without casting it to the appropriate type. The implementation of the "__question" view is shown below:



Don't get scared by the crazy looking Ids assigned to the hidden field. We are going to explain that in a moment. Let's move to the easy stuff first! The Model.Text will display the Text of the question. Model.Point will display the points associated with the question. After displaying the question we want to display the choices associated with the question. The foreach loop iterates through the choices in a question and render the "__choice" partial view. Once again you can put HTML code in place of the "__choice" partial view but it is a good practice to break a large HTML piece into small reusable components.      

The "__choice" partial view is where you display the radio buttons with the choice text. The implementation is shown below:



When the exam is displayed for the first time the else block is executed. Once again the crazy element naming will be explained in a minute. The RadioButton is displayed along with the text associated with the choice. If you run the page right now you probably would not see anything since we have not supplied the data to the view page "Publish.aspx". Let's perform that in the next section.   

Supplying the View with the Data:  

The ExamController is responsible for providing the data to the view. The Publish action is invoked when the user is directed to the Publish.aspx page.



Now, the exam will look something like this:



Looks pretty nice right!

Before we get too excited let's take a look at the Grade action in the ExamController.



If you remember the Grade action is invoked when the user submits the exam. The most important thing to note about the Grade action is the input parameter of type Exam. This means we are expecting an object of type Exam to be passed from the "Publish.aspx" page to the Grade action.

This conversion from plain fields to an object is performed by the model binding feature of ASP.NET MVC Framework. If you are not familiar with model binding then we highly recommend that you check out the following resources.

1) Populating Hierarchical Data Using Model Binders in ASP.NET MVC Framework
2) Introduction to Model Binders in ASP.NET MVC Framework

You should also note that our objective is NOT to build the complete exam object using the fields passed through Request.Form collection. We are just interested in the fields which are important to us. You might be wondering how to determine the important fields. A simple technique is to populate the key fields of all the objects that make the main object (Exam). Later you can fetch the complete objects using their key fields.

In Publish.aspx view page we are only interested in the Exam's Id field hence it was stored in the hidden field as shown below:



If we were interested in the Name of the exam then we should have stored the name in the hidden field also but since we have handled the Id of the exam we can fetch the complete exam object which will contain the populated Name field.

Let's move to the "__question" view and see how the Question object will be created and attached to the Exam object. The relationship between the Exam and the Question is one to many which means a single exam can consists of multiple questions. This relationship is represented by having a List<Question> object inside the exam instance. In order to populate the Questions for the Exam object we need a special collection syntax as shown below:




The above code will be rendered as follows:

 

Pay special attention to the name of the hidden elements. Does that ring a bell? Yes you are right! This is the same way you can access the Question object Id field. This also means that when the form is submitted the model binders is going to look at the name of the element and populate the Questions[0].Id field of the Exam object with the value of "1". Take a look at the following screenshot which shows the Grade action fired during debugging.



As, you can see the the exam object is populated with a list of questions. You should also note that we are not populating all the fields of the Question object. The fields such as Text, Point are left out since those fields can be populated using the "Id" field of the Question object.

The "__choice" partial view consists of the same logic with one exception. We don't have an OrderNumber field for the choice so how are we going to populate the choices in the Question object. Well, we don't need all the choices! Remember it is a select the best answer type of exam which means there is only one correct answer. We just have to populate the Question object with the choice selected by the user.

The implementation for the RadioButton in the "__choice" partial view is shown below:



The Model.Question.OrderNumber will make sure that the choices are mutually exclusive within a group of choices that are associated with a single question.

The above code will be rendered as follows:

      

This means that no matter how many choices the question has we will only populate the choice that is selected by the user. Take a look at the following screenshot that shows the Choice object populated with the user selection.



Once again we are only interested in the "Id" field of the Choice object. We can populate all the other fields by using the "Id" field to fetch the object from the storage.

Grading the Exam:

To keep the article simple we are going to use the ExamService to perform the grading. In real application you should using a separate grading service interface.   

The Grade method is shown below:



The Grade method first fetches the actual exam from the storage and then alter the choices of the exam using the exam submitted by the user. Finally, the Grade method returns the Grade object which is displayed to the user.

Displaying Grade to the User:

The final step is to display the grade to the user. This is accomplished in the Grade.aspx view page which is strongly typed to use the Grade object as shown below:



Most of the code is identical to the "Publish.aspx" page. The output of the grade page is shown below:



The correct answers are highlighted with light green color while the incorrect answers are left plain. The CSS class is applied in the "__choice" partial view using the IsSelected and IsAnswer fields of the Choice object.



You can make the result much better by applying different styles to the correct and incorrect answers.

Conclusion:

In this article we learned how to create a simple multiple choice exam using ASP.NET MVC Framework. By having complete control over the rendered HTML we can modify the output without any restrictions. In the next article we are going to demonstrate how to include questions with multiple correct choices and a floating clock to make our exam look more realistic.

[Download Sample]