First Impressions of Pluralsight Assessments

Recently, Pluralsight began allowing their subscribers to take assessments on specific topics. Assessments are a quick way for subscribers to test their knowledge on a select number of topics, ideally, ones that they watched on PluralSight.

What makes these tests unique is that the questions that subscribers are presented with are based on how well they answered the previous question. Answer a question correctly and the next question will be more difficult. Conversely, answer incorrectly, and the next question will be easier. In addition, each question has a countdown timer indicating the amount of time the subscriber has to answer the question.

If I’m not mistaking, this technology comes from PluralSight’s purchase of Smarterer in 2014.

Before an assessment goes live, it remain in beta until at least 50 tests are completed. I’m assuming this is so they can re-calibrate the difficulty rating of each question and perhaps adjust how much time the subscriber is given to answer each question.

After the assessment, based on how the subscriber scored, they are recommended a list of courses from the Pluralsight library they should watch.

Overall Impression

Personally, I really enjoyed taking several assessments on topics I felt strong in and the ability for tests to adapt based on how well a question was answered makes it just challenging enough to be fun. However, I feel that the countdown timer is a bit of a distraction and I feel rushed to answer a question. My approach now is to first look at the time and based on the amount of time I have, either speed read the question and possible answers or take my time and carefully read.

I was able to achieve decent scores in several of the assessments which I wish I could publicly share. This is a feature request I have made to Pluralsight, so hopefully that gets eventually implement. Until then, here are my scores:

MVC 5MVC 5 JavaScriptJavaScript
HTML5HTML5 AngularJSAngularJS

Strongly Typed Views in MVC

In ASP.NET MVC, we have a couple of options for passing data from a controller to a view:

  • ViewData
  • ViewBag
  • View-specific data model

ViewData

The ViewData  property is on the ControllerBase  which all controllers derive from and is accessible from both a controller and a view. It is of type ViewDataDictionary , which implements IDictionary<string, object> . To pass any piece of information to a view using the ViewData , we simply set the value in an action method:

Then, from within the view, we access the value by using the same key:

ViewBag

The ViewBag  is essentially a wrapper around the ViewData dictionary that uses dynamics to allow us to access the data using properties off of the ViewBag property rather than accessing each value by it’s key name. This property too, is off on the ControllerBase.

Then, from the view, we access the same property:

Both of these approaches allow us to pass in information to a view without creating a new class or adding a property to an existing class, however there are several disadvantages with both approaches:

No standard set of properties that get passed into the view
Since the data is passed into the view using essentially a dictionary, there is no way to enforce/ensure that expected values are provided. As such, if we wanted to use a common _Layout page to display the number of unread messages, the _Layout page would have to read the dictionary using a string-based key and check if an item is returned using that key.

In addition, since ViewData is a Dictionary<string, object> , whenever we read a value, we must first check if it is null, and then try to typecast it into a type that we expect it to be.

No intellisense
When working on the view and need to read a property, you will need to look back at the action method to see what the property was called instead of allowing Intellisense to help you find the property.

No compile time checking of our views
Because the ViewData and ViewBag are just dictionaries, there is no way for the compiler to know if a property being accessed from the view was ever set in the action method. It is only at run-time that the bug will present itself.

—–

A Better Approach

Using strongly-typed views that inherit from a base view model we can avoid the problems I just listed. Having the base view model will give us a common set of properties that _Layout page can depend on, we’ll have Intellisense when reading a property from the model and if we turn on view compilation, we’ll also get compile-time checking.

The Model

/Models/ViewModels/BaseViewModel.cs

Base class that all view models will inherit from:

/Models/ViewModels/Home/IndexViewModel.cs

Derived class that will be used by the Index view:

The Controller

/Controllers/BaseController.cs

Base controller that all controllers will derived from. It contains a protected method that will be used to set the standard BaseViewModel  properties. When calling this method, the caller has the option to provide a page title. Also, note that this method is responsible for retrieving and setting the number of unread messages instead of requiring each action method to set this value.

/Controllers/HomeController.cs

The HomeController  will derive from the BaseController  and call the base method to set the properties of the base view model. The Index action method will only deal with setting additional properties needed by its view.

The View

/Views/Home/Index.cshtml

The view works directly with the view model that is specific for this view and does not have to worry about properties on the base view model. Those properties will be handled by _Layout.cshtml

/Views/Shared/_Layout.cshtml

The _Layout page can now access the properties on the base view model in a strongly-typed way with Intellisense and compile-time checking:

Summary

Using a BaseViewModel  we have a structured way of passing data from the controller to the view. Using a BaseController  allows us to move the logic responsible for setting common properties into one centralize place. From the views we can leverage Intellisense to help us access the correct properties from our model and get compile-time errors whenever we access properties that do not exist in our model.