Friday, January 14, 2011

Highlighting Active menu item the ASP.NET MVC way

As you deduced from the title we will investigate different options we have to highlight menu items in the view based on our user's current navigation in the web application.

Requirement:

  • A single menu items usually ends up representing multiple views
  • I assume you are using ASP.NET MVC areas to logically group views in the application together 
  • and you want to highlight/select the menu item that represents the current section/area that your user is working on
  • You implemented a menu system on the master page(lay out page as MVC 3 nerds wish to name it) as it is shared by all views of the application.
To meet the above requirement we need to device a mechanism to:
  1. Keep track of the  current section/area of the application that our user is using. 
  2. High light the menu item
  3. and finnally pass the current section to the view 
Lets us dig into the solution using a simple example, for the menu system displayed below, we want Posting menu item to get highlighted for any view in the posting area/section and like wise for the rest of the areas. 


I created the TopMenu enum to represent the menu items:

and this HtmlHelper extension for reasons that become apparent as you read on :

and finally the portion of the view in the master page that contains the menu items : 


For those of you who got lost, the ActiveMenu HtmlHelper extension returns either nothing or something like class="active" and web designers know how to associate a style to the css class.Taking it from here our next concern is how we are going to determine and pass the proper TopMenu object as a ViewData entry.

The first dirty option



 Obviously this is not a good option, not maintainable and not clean!

The Second option
The second option is to use ASP.NET MVC ActionFilter to keep the logic DRY.


The idea is simple the filter encapsulates the logic to determine the active menu and add the correct TopMenu object to ViewData, neat right? But we still need to apply [MenuFilter] to controller actions or on every controller or better yet on a base controller if you have one.

The Third option


This is my preferred method: The only difference with option 2 is how I am going to apply the Filter to my actions: Here is where global filter comes in handy. I don't want to discuss global filters on this post because that is not my intention(DRY ... aha), refer Brad Wilson's blog about the subject.

Here is the filter provider:


Once we have the filter provider registering our MenuFilter globally is very simple, include the following code snippet in the Global.asax.cs:
Take it easy, the first line is not part of menu system, as depicted above it only takes three lines to register your filter globally. You probably need the Filter for HTTP GET requests that is why we have the lambda expression on the third line.


 I appreciate your time, Thanks.


Abiy 

Wednesday, January 12, 2011

Posting a javascript array using jQuery to ASP.NET MVC controller action

Posting a data from a JavaScript has become a lot more easier  as more and more cool jQuery plugins continue to avail themselves on top of the core jQuery  library. In my current project I needed to post a JavaScript complex array object back to my ASP.NET MVC controller action which expects  a collection of custom objects. An example is worth a thousand words, I don't want to beat around the bush while you wait:
First the model:








and controller action:

So the idea here is to post a JavaScript array of Employee's to the controller action ExportUser, here is the JavaScript constructor for the Employee object and other utility JavaScript functions.



I like creating my JavaScript in this style, it some how allows me to modularize my script , as you see the above script contains everything we need to achieve our goal namely posting arrays of custom objects. The Employee constructor "create" begins at line number 12 and runs all the way to line number 16 in fact it very short. Never include server URLs in your JavaScript instead pass them and any other view specific data elements to your script, that is why the init method is there for. 



Or using the new Razor view engine  syntax: by the way working with razor is exciting.


I am sure this will get the message across, though the example is simplified. Now let us see the underpinnings of  the function Employee.post(). This function wraps the jQuery ajax function inside, meaning you need to have a reference to jQuery in your view to get this up and running .The other heavy lifting is done by json2.js  at line number 23, the call toJSON() converts the input array to json format making it easier for the jQuery $.ajax function. Since we are sending the data as json the content type for the ajax request should be  application/json and this allows the MVC model binder and json value provider to reassemble the data and pass it on to the controller action. Whereas model binders are used to bind incoming data to an object model, value providers provide an abstraction for the incoming data itself. How awesome is this? Leave a comment and any questions.

Cheers!