Use case and goals
Often times in building a web application we have the need to store some type of user configuration for the lifecycle of a user's visit on the site. Typically we turn to the Session to store this data and we accomplish that by posting some type of form data to a server side script and then reloading the page.
With ASP.NET MVC 3 it is easy to write up controller actions that work with JSON data and add some jQuery code in views to interface with those actions via Ajax. We can use that approach to capture and post user settings to some server side code and return the user's settings back without having to reload a page or redirect the user.
We will be creating a prototype application that will have a list page that displays a list of data records consisting of a name and a description. It will allow the user to set the list view to either rows or a grid of blocks. There will also be an option to show or hide the description. When the user sets their desired options we will store them in the Session state. Finally, we want to update the view without reloading the page.
Scaffolding for read/write with the Session
We begin by creating a class for our settings structure that we will use with model binding to store and work with our JSON data from our view. This allows us to use one key/value pair in our Session state instead of storing a key/value for each of our settings. It also provides us with additional control over our data content, thus we can craft some code to protect ourselves from potential cross site scripting vulnerabilities since we will be receiving post data into our action method. Our class will be named ListSettings and will contain two properties named ListView and ShowDescription.
Listing 1: ListSettings.cs
With our settings class defined we can build out our SettingsController class. This class will contain an action method named Save that will take in a ListSetting object, save it in the Session state, and return the object (we will learn why when we get into the jQuery code later in the article). We will also create an action method named Load that will instantiate a default ListSettings object, get the data in the session (if any) and return it as a JSON object.
Listing 2: SettingsController.cs
Controllers and views for the UX
Next we need to set up our user experience layer. We will add a home page and a list page so we can navigate between the two and test our session state. The HomeController will contain the action methods Index and List. Since we want to handle all of our UX updates via Ajax we do not need to add any logic in here to load up the settings for our display.
Listing 3: HomeController.cs
The Index.cshtml view file contains a heading tag to let us know where we are at.
Listing 4: Index.cshtml
The List.cshtml view file will contain the buttons to set the list view type, a button to toggle the description option and an unordered list of our sample data. We will decorate the unordered list with a CSS class named Hidden that will hide the display of the list until we can determine the user settings via some jQuery. The buttons and the unordered lists will get id attributes so we can target them within our jQuery. The data in the list items will also get CSS classes for some styling and to handle the toggle of the description. The html markup portion of the List.cshtml file looks like:
Before we craft the jQuery code let's build out the CSS that we need. We can add the following CSS to the existing Site.css file that is in the default MVC 3 project.
The Button class styles our span tags to make them look interactive. The Hidden class sets the display to none. We use this class for the unordered list as well as the description elements. Using the ItemListing id, we set a fixed width on the unordered list so our grid layout will be a set number of blocks wide (in this case it will be 3). We also normalize the styling on the unordered list by setting the list type to none and the margin/padding to zero. This will remove the disc glyph and left indention so we can have our list looking like rows or columns of blocks. The Name and Description classes add some styling to our text. Finally, the Rows and Grid classes set the style of the li elements to control the way the list items are viewed. The Rows sets the width of each li to the same width as the unordered list. The Grid sets the width on each one smaller, floats them to the left and adds some margin to the right and bottom of each so they don't run into each other. The width of the unordered list will force the grid blocks to wrap, thus achieving the 3 column look.
The jQuery code in the List.cshtml file will handle the user interaction with the settings buttons and updates to the list view. We begin by defining a settings variable that will be global so our functions can access the data in it. Then we will add the jQuery on document load block to wire up our button clicks and add a call to a function called LoadSettings. The final part of script will be our functions to save and load the settings, a callback function to handle the settings loaded event, and a function to set the list view.
The code for setting the list view type handles setting the ListView property of the settings JavaScript object to the selected list view and calls the SaveSettings method. The SaveSettings method posts the settings object to our Save action method in the SettingsController and upon success receives the returned JSON object from that action method and calls the SetListView function. The code to toggle the description visibility sets the ShowDescription property to the opposite of what it currently is (in effect, toggling its state) and then makes the call to SaveSettings.
The SetListView function makes the view changes to the ItemListing by removing the Hidden class and each of the possible list view classes and then adds the selected list view class (we are using the name of the list type as the name of the CSS class). It also checks the ShowDescription property and either removes or adds the Hidden class on the elements with the Description class.
The LoadSettings function makes a post call to the Load action method in the SettingsController and upon success calls the OnSettingsLoaded function. The OnSettingsLoaded function sets the returned JSON object to our settings global variable and then calls the SetListView function. The reason we need to set the global settings object here is so the event handler for the toggle description button has access to the current settings for the ShowDescription property.
That's all that is needed for our view. The end result for our List.cshtml file:
Listing 5: List.cshtml
The last piece we will add is some navigation in our Layout.cshtml file so we have a way to switch back and forth between the home and list pages.
Listing 6: _Layout.cshtml
Now we can run our application, change up our view settings, and navigate back and forth between the home and list pages to see that our settings are remaining in their proper state.
Adapting to changes in requirements
By setting up our UX layer to save and load our settings via JSON we have decoupled the logic of doing the actual state storage from our display. This allows us to make changes to the way we store those settings without having to change our view. For example, we could change our storage logic to use cookies instead by updating our SettingsController class.
Listing 7: SettingsController.cs
With this approach we are able to store and retrieve data on the fly from our application interface and can respond to the user's request for change with an instant update rather than a page reload. Enhancements to the user experience accomplished with relative ease using MVC and jQuery.
About Justin Schwartzenberger
 |
I have been entrenched in web application development for quite a while and have traversed the syntactic jungles of PHP, classic ASP, Visual Basic, VB.NET, and ASP.NET Web Forms. However, I have found a guilty pleasure in ASP.NET MVC since its beta launch and have since refactored my web stack focus...
This author has published 3 articles on DotNetSlackers. View other articles or the complete profile here.
|
You might also be interested in the following related blog posts
Updated SilverTwit Code for MSDN Magazine
read more
How do ASP.NET Application_ Events Work
read more
CodeDigest.Com Article,Codes,FAQs - April,2009
read more
Using NHibernate with multiple databases
read more
What is .NET RIA Services?
read more
Convert Web.UI Grid into a data entry spreadsheet
read more
Sir DevFishs Crusade of Enlightenment
read more
Identity Maps
read more
Session Slides and Samples from Microsoft ASP.NET Connections
read more
Running the Same Query Against Multiple Databases
read more
|
|
Please login to rate or to leave a comment.