Json.Net Action Result with Asp.Net MVC

Well this has probably been done 100 times before but so what, the world could always use more code. When working with ASP.Net MVC I started and fell in love with James Newton-King’s Json.Net library. It is simple awesome and does an amazing job in different parts of my app. The control over the serialzation and deserialization is very good and thought it would be well suited for my MVC application.

You might be thinking, why not just use the one that comes with .Net. It’s in the box and is just as good. Well my preference was control, I wanted to control my model better and I wanted to output Json differently in different situations. So I created a new ActionResult that does just that but with the Json.Net library. Enjoy!

Example usage in any controller action:

public ActionResult List(int Year, int Month)
{
    if (Year == 0)
        Year = DateTime.Now.Year;
 
    if (Month == 0)
        Month = DateTime.Now.Month;
 
    var calendarMonth = _calendarService.GetCalendarMonth(Year, Month, !this.IsAdmin());
 
    return new JsonNetResult(calendarMonth);
}

The code is below, but it can also be downloaded here and found on Github here.

using System;
using System.Text;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
 
namespace com.bytecyclist
{
    public class JsonNetResult : ActionResult
    {
        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }
 
        public JsonSerializerSettings SerializerSettings { get; set; }
        public Formatting Formatting { get; set; }
 
        public JsonNetResult()
        {
            SerializerSettings = new JsonSerializerSettings();
 
            SerializerSettings.Converters.Add(new JavaScriptDateTimeConverter());
            Formatting = Formatting.None;
        }
 
        public JsonNetResult(object data)
            : this()
        {
            Data = data;
        }
 
        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
 
            var response = context.HttpContext.Response;
            response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
 
            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;
 
            if (Data == null) return;
            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
 
            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);
            writer.Flush();
        }
    }
}

Simple Asp.Net MVC Navigation Menu

Well it’s October first, it has been a really long time since I have last written anything. Oh well. Recently I have been working on applying some updates to an MVC site I maintain, as usual I updated the dependencies, ran some tests, and looked over the code. It’s been a while since I last opened the project since it has been in production. Of course, I was not happy with a couple things in the application and was constantly fixing the same bugs in the navigation menu.

There are always the same questions with a navigation menu, how do you render the html, how do you know what item is selected, how to achieve 2 level menus, and how do you trim by security. To give some history; I went from defining only a single level with no selection (action links in an un-ordered list). Then I found a project on codeplex called ASP.NET MVC SiteMap Provider, this is great it has a ton of features, fits the provider model of ASP.Net, easy to define and use in simple cases. Unfortunately, it is not as mature as I would like. Plus it adds another dependency that is hard to work with and does not always work the way I would expect it to. Needless to say it is buggy (my opinion and experience only, others may differ).

Which brings me to my subject line. I wanted to create my own navigation system and have full control over the levels, rendering and selection of the items. Perfect, I needed a partial to render the menu and top level items in my own un-ordered list. I also needed some helpers to render those items in my partial, in this case the top level is a list of my controllers.

<ul id="navigation">
    <%= Html.NavItem("Home")%>
    <%= Html.NavItem("Calendar")%>
    <%= Html.NavItem("Media")%>
    <%= Html.NavItem("Messages", "Forum", "Index")%>
    <%= Html.NavItem("Goods", "Catalog", "Index")%>
    <%= Html.NavItem("Links", "Link", "Index")%>
    <%= Html.NavItem("Contact")%>
    <%= Html.LoginStatusNavItem() %>
</ul>
 
<div class="clearboth"></div>
 
<ul id="subnavigation">
    <%= Html.SubNavListItems() %>
    <%= Html.NavItem("Join Our Mailing List!", "Contact", "MailingList") %>
</ul>

I also added a helper to render the login/logout link in the navigation based on whether the request was authenticated. The second level navigation was where the work came in. Essentially I wanted to render some of the actions from the current controller based on a attribute assigned to the action. The rending will then sort the list based on the sort order and perform security trimming.

[NavigationItem("About Us", 0)]
public ActionResult Index()
{
    return View("Index", GetIndexModel());
}
 
[NavigationItem("Secured Page", 0), Authorize]
public ActionResult Admin()
{
    return View("Index", GetIndexModel());
}

In order to do that I created a custom Attribute to store the link text and the order it should be in.

[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
internal sealed class NavigationItemAttribute : Attribute
{
    public NavigationItemAttribute(string text)
        : this(text, 0) { }
 
    public NavigationItemAttribute(string text, int order)
    {
        Text = text;
        SortOrder = order;
    }
 
    public string Text { get; private set; }
    public int SortOrder { get; set; }
}

After that I needed a way to cache all this information in order to look it up later from my helpers. Populating this cache involves doing some basic reflection and type checking of controller actions. Then storing the results in a dictionary based on controller name as the key and a list of actions with the NavigationItemAttribute (stored as a ControllerNavigationItem, which is a POCO object to store data). Since I only wanted to do this reflection once, I created a singleton to do the work.

public sealed class ControllerNavigationItemCollection
{
    static ControllerNavigationItemCollection _instance;
    static readonly object padlock = new object();
 
    public IDictionary<string, IEnumerable<ControllerNavigationItem>> Controllers { get; private set; }
 
    ControllerNavigationItemCollection()
    {
        Controllers = new Dictionary<string, IEnumerable<ControllerNavigationItem>>();
        PopulateCollection();
    }
 
    private void PopulateCollection()
    {
        var asm = Assembly.GetExecutingAssembly();
        var controllers = (from t in asm.GetTypes()
                           where
                               typeof(Controller).IsAssignableFrom(t) &&
                               typeof(Controller) != t
                           select t).ToList();
 
        controllers.ForEach(t => Controllers.Add(t.Name, GetControllerNavItems(t)));
    }
 
    private static IEnumerable<ControllerNavigationItem> GetControllerNavItems(Type controllerType)
    {
        var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
 
        var actions = (from a in controllerDescriptor.GetCanonicalActions()
                       let subNavAttr = (NavigationItemAttribute)a.GetCustomAttributes(typeof(NavigationItemAttribute), false).SingleOrDefault()
                       let authorize = a.GetCustomAttributes(typeof(AuthorizeAttribute), false).SingleOrDefault()
                       where a.IsDefined(typeof(NavigationItemAttribute), false)
                       select new ControllerNavigationItem
                       {
                           Action = a.ActionName,
                           Controller = a.ControllerDescriptor.ControllerName,
                           IsSecure = authorize != null,
                           SortOrder = subNavAttr.SortOrder,
                           Text = subNavAttr.Text
                       }).AsEnumerable();
 
        return actions;
    }
 
    public static ControllerNavigationItemCollection Current
    {
        get
        {
            lock (padlock)
            {
                return _instance ?? (_instance = new ControllerNavigationItemCollection());
            }
        }
    }
}

Finnaly to render the second level navigation I look up the list based on the current controller and loop over the items, only rendering the secure and authenticated items or the public items in the order defined by the attribute.

In hindsight, there are some things I could have made better or more features I could support. Currently it just checks to see if your logged in and doesn’t take into account any specific roles on the action. Also it lacks support for MVC 2 Areas, but I don’t have any yet so I will cross that bridge when I get to it. This solution was simply an exercise for me in creating a singleton, using reflection to find controllers and actions, and to fill a common need in an ASP.Net MVC application. Hope you found this interesting or useful.

Download the code here or check out the Gist on Github

jMonthCalendar Options, Events, & Methods Documentation

In this post I am going to cover all the custom event/options as well as methods that can be configured and used in jMonthCalendar. All of these are options that can be supplied at initialization in order to manipulate the calendar further or be able to tie into some additional logic ot rules. As well as methods that are exposed for manipulating the calendar after initialization. This is my first attempt at formal documentation, so bare with me.

Continue reading

jMonthCalendar-1.3.2-beta Release

I have released a new version of jMonthCalendar (1.3.2-beta). Below I will provide a sample of the use of event callback as options. Well this release is pretty straight forward for the most part. It includes changes to how the custom events are fired mostly and addresses various bug fixes. As well as includes some reduction in file size. UPDATE Beta2 is released to fix some minor bug issues.

Continue reading

jMonthCalendar 1.3.0 Beta

jMonthCalendar has reached a new milestone! It now supports multi-day events (events that span multiple days). Plus it retains all the same features as before including drag and drop and event stacking. This release is a huge change from the previous version and is thus labeled as Beta. Most significant to the change is how events are rendered onto the calendar. In this post I am going to go over the new features and how they will affect existing users. I will also try to cover some of the new functionality and how it might be used. Continue reading

log4net Dynamic Properties in XML Configuration.

I just learned about a new feature today of log4net that would have saved me a few hours of time had I known or been able to find this earlier.  I learned that you can have dynamic properties stored into log4net’s global context from code and then access them from the XML configuration file. This is useful in the case where dynamic configuration of log4net is needed. Continue reading

ASP.NET Bundle launch giveaway

Unit Testing ASP.NET? ASP.NET unit testing has never been this easy.

Typemock is launching a new product for ASP.NET developers – the ASP.NET Bundle – and for the launch will be giving out FREE licenses to bloggers and their readers.

The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both Typemock Isolator, a unit test tool and Ivonna, the Isolator add-on for ASP.NET unit testing, for a bargain price.

Typemock Isolator is a leading .NET unit testing tool (C# and VB.NET) for many ‘hard to test’ technologies such as SharePoint, ASP.NET, MVC, WCF, WPF, Silverlight and more. Note that for unit testing Silverlight there is an open source Isolator add-on called SilverUnit.

The first 60 bloggers who will blog this text in their blog and tell us about it, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET dedicated blog, you’ll get a license automatically (even if more than 60 submit) during the first week of this announcement.

Also 8 bloggers will get an additional 2 licenses (each) to give away to their readers / friends.

Go ahead, click the following link for more information on how to get your free license.

New Project Home For jMonthCalendar

It has been awhile since I have had anything to announce with jMonthCalendar. I have been quite busy lately and have been procrastinating at bug fixes and enhancements. Lately, I’ve been working on an idea to set up project wiki, issue, and source management system using Redmine and Subversion. My current host does not play well with Subversion and was lacking on memory and access needed to run Redmine the way I wanted. So I have moved the project and source over to Google Code. Continue reading