views:

430

answers:

6

I'm trying to fill a JSON object with a list of items from the database when the page first loads. This list of items comes from the database. Right now, I've strongly typed the View and am looping through the list of items to build an HTML unordered list, and then in the JavaScript building the JSON object from what's been output in the HTML. But this is clunky.

Ideally, I'd like to take that data from the database in the Controller, fill an object (or variable), and send that variable over to the JavaScript to use there, and skip the HTML in between (the HTML will be updated dynamically using jQuery). The variable that arrives in the JavaScript doesn't have to be a JSON object, but it does need to hold information that I've populated from the Controller. From there, I can build the JSON object in the JavaScript.

A friend told me this is possible and he currently uses this method, but has never tried it in ASP.NET MVC. Any ideas?

CLARIFICATION: I should have been more clear in my original question, but I am trying to send the variable/JSON over to an external javascript file, rather than handle the JSON object/create it inline within tags.

A: 

Yep. Find a JSON serializer for the language you're using from here: http://www.json.org/

Then once you've instantiated and populated your data objects, you should be able to invoke a .toJSONString() method (or similar) which will spit out the JSON for transmission to the client.

Sam C
I guess I'm also wondering how best to transmit it to the client. Is AJAX the only way to go, or is there some built in method in MVC?
Mega Matt
A: 

You could just render some JavaScript instead of the unordered list in the HTML. So if you wanted to be able to access a list of JSON objects then something like

<html>
<body>
  <div>...</div>

  <script type="text/javascript">
    var list = {
      <% foreach(var item in Model) { %>
        { x:<%= item.X %>, Y:<%= item.Y %>, Z:<%= item.Z %> },
      <% } %>
    };
    // or
    var x = <%= Model.MySerializedJson %>
  </script>
</body>
</html>

Or you could use an Ajax call after the page has been rendered.

David G
Thanks Dave for the answer. I commented on another answer in a similar capacity, as I am trying to keep all JS in an external file, rather than inline within <style> tags. I also think I'd like to serialize on the server side, rather than create the JSON object on the client. Once I have that JSON object on the server side, I'm having a hard time figuring out how to inject it into the external JS file. Thanks.
Mega Matt
The above is serialized on the server but if you want to keep your javascript external then an AJAX call to a controller method returning a JsonResult would be the way to go. Alternatively you could have your controller return a complete js file and include a script tag with src="/Controller/MyControllerGeneratedJsFile.js"
David G
I like this. How do you serialize lets say a list of Person objects to a json string (which is what I assume Model.MySerializedJson is)?
User
+2  A: 

You can assign JSON directly to a [javascript] variable as it is valid javascript.

.NET includes a serializer in

System.Web.Script.Serialization.JavaScriptSerializer

In your controller you probably have something like a list that you are passing in:

ViewData["MyData"] = new List<int>() { 1, 2, 3 };

Then you could parse it inside the view with:

var serializer = new JavaScriptSerializer();
string data = serializer.Serialize(ViewData["MyData"]);
// data will be [1,2,3] I think
// objects with members will have data like { "MyVariable": "MyValue", ...}

You could also store an variable in the global scope and push() values onto it as you loop.

var MyData = new Array();

MyData.push(1);
MyData.push(2);
MyData.push(3);
envalid
That sounds perfect, and thanks for the answer. However, I should have been more clear because I'm trying to keep all javascript in an external file. That would work well if I used inline javascript (in <script> tags), but is there a way to get that over to the external javascript file once I've serialized in the Controller? Thanks.
Mega Matt
At that point it would be separated from the view. You could try storing it in the session (or a get variable) then use another view to generate the javascript. IMO using renderpartial would be a better solution, you still get the loos(er) coupling but don't deal with a second render or bloated session variables.
envalid
+1  A: 

This is how Flicker tackled this problem rather recently:

http://code.flickr.com/blog/2009/03/18/building-fast-client-side-searches/

The fastest way to do this, according to their observations, is to send the data as delimited text and then use String.prototype.split() to get the job done rather than a JSON parser.

Since we had already discovered that some methods of string manipulation didn’t perform well on large strings, we restricted ourselves to a method that we knew to be fast: split(). We used control characters to delimit each contact, and a different control character to delimit the fields within each contact. This allowed us to parse the string into contact objects with one split, then loop through that array and split again on each string.

Kris Walker
+1  A: 

In your controller just

return Json(yourObject);

instead of

return View(yourObject);

the MVC framework will serialize almost anything into JSON, just watch out for linq-to-sql objects that have a circular relation.

If you then call this with jQuery ajax you will get a JSON object in "data".

If you want your controller to be able to return both html(view) or json you can check if the request is an ajax request like so:

if(Request.IsAjaxRequest())
{

}
Oscar Kilhed
Odge, This is the way that I've begun to implement this, even if it means a second hit to the server once the page loads just to get that data (I was trying to keep it to one so that the data is there on page load without the need to hit the server again). But if I stick with this route, I do want the Controller to be able to return a View or the JsonResult. Question here: what is my return type for the Controller at that point? Some of the time it would need to be ActionResult, and other times it would need to be JsonResult. Parameters will also vary by call...
Mega Matt
The return type will still be ActionResult since both JsonResult and ViewResult inherits ActionResult.
Oscar Kilhed
+1  A: 

Others have commented on various ways to turn your data into JSON. If you want your external JS file to have this JSON data, then you'll need to route requests for that JS file appropriately so that it is served as a dynamic request rather than one for a static file. Once you do so, you can dynamically generate the JSON part of the external JS file.

Bernard Chen