Return Multiple Objects Using ASP.NET MVC'S JsonResult Class

Posted by: Malcolm Sheridan , on 3/4/2010, in Category ASP.NET MVC
Views: 75602
Abstract: The following article demonstrates how to return multiple objects in ASP.NET MVC using the JsonResult class.
Return Multiple Objects Using ASP.NET MVC'S JsonResult Class
 
I'm always amazed at all the things you can do with ASP.NET MVC with a little thought. I recently had to return multiple objects from an MVC action to a piece of JavaScript code. This was all handled by jQuery's $.getJSON function. Instead of querying the server multiple times for the data, why not return multiple objects from the action to the JavaScript? Sounds easy an it is. This code sample is using the latest jQuery 1.4.2 library and can be downloaded here.
For this article I've got a scenario where I'm using ASP.NET MVC and I want to make an ajax request to an action, and receive multiple JSON objects from the action in one call. This can be accomplished easily by creating an object like the following:

 

C#
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult SomeAction()
{
      return Json(new {});
}
VB.NET
<AcceptVerbs(HttpVerbs.Get)> _
Public Function SomeAction() As JsonResult
      Return Json(New With {})
End Function
The return object for this example will be an anonymous object. For this example, I'm going to return an object that lists the months in a year, and also another object which displays the environment variables from your computer. Now I want these two objects returned when I make one ajax call through JavaScript. Here's the server code below. First off I'm going to create a class that holds a Text/Value object:
C#
public class TextValue
{
      public string Text { get; set; }
      public string Value { get; set; }
}
VB.NET
Public Class TextValue
      Private privateText As String
      Public Property Text() As String
            Get
                  Return privateText
            End Get
            Set(ByVal value As String)
                  privateText = value
            End Set
      End Property
       Private privateValue As String
       Public Property Value() As String
             Get
                   Return privateValue
             End Get
             Set(ByVal value As String)
                   privateValue = value
             End Set
       End Property
End Class
 
Now here's the action:
C#
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult ReturnMultipleObjects()
{
      var info = new DateTimeFormatInfo();
      return Json(new
            {
                  EnvironmentVariables = (from p in Environment.GetEnvironmentVariables().Cast<DictionaryEntry>()
                        select new TextValue()
                        {
                              Text = p.Value.ToString(),
                              Value = p.Key.ToString()
                        }),
                        MonthsInYear = (from p in Enumerable.Range(1, 12)
                              select new TextValue
                              {
                                    Value = p.ToString(),
                                    Text = info.GetMonthName(p)
                              })
                        }
            );
}
VB.NET
<AcceptVerbs(HttpVerbs.Get)> _
Public Function ReturnMultipleObjects() As JsonResult
      Dim info = New DateTimeFormatInfo()
       Return Json(New With {Key .EnvironmentVariables = ( _
            From p In Environment.GetEnvironmentVariables().Cast(Of DictionaryEntry)() _
            Select New TextValue() With {.Text = p.Value.ToString(), .Value = p.Key.ToString()}), Key .MonthsInYear = ( _
            From p In Enumerable.Range(1, 12) _
            Select New TextValue With {.Value = p.ToString(), .Text = info.GetMonthName(p)})})
End Function
In the code above, I'm returning JSON that contains two objects, EnvironmentVariables and MonthsInYear. To return two objects, the action's result is Json, but I'm using new {} to return an anonymous object:
C#
return Json(new {});
 
I simply create new objects by supplying a name and a value for the object:
EnvironmentVariables = (from p in Environment.GetEnvironmentVariables().Cast<DictionaryEntry>()
                        select new TextValue()
                        {
                              Text = p.Value.ToString(),
                              Value = p.Key.ToString()
                        })
VB.NET
EnvironmentVariables = ( _
    From p In Environment.GetEnvironmentVariables().Cast(Of DictionaryEntry)() _
    Select New TextValue() With {.Text = p.Value.ToString(), .Value = p.Key.ToString()})
 
Each object is separated by a comma. To receive the data back through Ajax I have to decorate the action with the AcceptVerbs attribute:
[AcceptVerbs(HttpVerbs.Get)]
 
 
This action will only respond to HTTP Get requests. Let's add some JavaScript to the page to query the action:
 
<div id="demo"></div>
<form method="get" action="/Home/ReturnMultipleObjects" id="GetData">
      <input type="submit" value="Get Data" />
</form>
<script language="javascript" type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
<script language="javascript" type="text/javascript" src="http://jtemplates.tpython.com/jTemplates/jquery-jtemplates.js"></script>
<script language="javascript" type="text/javascript">
        $(function() {
            $("#GetData").submit(function(e) {
                e.preventDefault();
                $.getJSON($(this).attr("action"), $(this).serialize(), function(data) {
                    process.template($("#demo"), data, "/Templates/Demo.htm");
                });
            });
        });
 
        var process = function() {
            return {
                template: function(element, data, url) {
                    element.setTemplateURL(url).processTemplate(data);
                }
            }
        } ();       
</script>
 
When the user submits the form, I am hijacking the form so the HTTP Get request can be performed via ajax. Here's a view of the data being returned in Firefox's Firebug add-on.
 
AddOn_1
 
AddOn
Then if you use jTemplates, you can access both objects and render them to the client:
<h2>
    Months in Year</h2>
<select id="SelectDay">
    {#foreach $T.MonthsInYear as data}
     <option value="{$T.data.Value}">{$T.data.Text}</option>
    {#/for}
</select>
<br />
<h2>
    Environment Variables</h2>
    <table>
    {#foreach $T.EnvironmentVariables as data}
        <tr><td>{$T.data.Value}</td><td>{$T.data.Text}</td></tr>
    {#/for}
    </table>
</select>

This is a great way to return multiple objects to the client. Nice and simple. The entire source code of this article can be downloaded over here

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, a Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Being an ASP.NET guy, his focus is on web technologies and has been for the past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with jQuery and JavaScript. He also writes technical articles on ASP.NET for SitePoint and other various websites. Follow him on twitter @malcolmsheridan


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Ryan Jacka on Wednesday, March 31, 2010 8:28 PM
Yay for jQuery and jTemplates... all this work is making me hungry from some Kim Chi!
Comment posted by Malcolm Sheridan on Saturday, April 10, 2010 4:57 AM
Me too!
Comment posted by donk on Tuesday, November 16, 2010 11:54 AM
How can you "thoroughly love ASP.Net and Javascript" ?  Seriously

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel