Building this type of application is really a totally new type of programming for me and has really been putting my brain (and whiteboard) through the some long nights. Over the last few weeks I've really been able to see it all come to light. I'm shooting at a moving target (so to say) and there are changes that pop up along the way that change the system at it's core, where I'm forced to change how objects are constructed and so forth. While I could go on and on about the application I'm working on and all of the problems I've been faced with recently, the topic for this post is strictly related to how easy it is to serialize server side objects to the client.
Problem
I needed a way to represent server side memory objects as client side javascript objects. I have a set of div tags that need to be represented on a canvas (another div) and the user needs to be able to interact with them. Most importantly, I didn't want to re-invent the wheel entirely in javascript by creating all new classes and so forth.
Solution
Json.
Example
Let's say I have an object called "Person" that has a few properties and a collection of PhoneNumbers.
Person
- Name
- Address
- City
- State
- Zip
- PhoneNumbers[]
- Type
- Number
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public IList PhoneNumber { get; }
public class JsonSerializer : JavaScriptConverter
{
// override SupportedTypes, Serialize(), & Deserialize()
}
}
class PhoneNumber
{
public string Type { get; set; }
public string Number { get; set; }
public class JsonSerializer : JavaScriptConverter
{
// override SupportedTypes, Serialize(), & Deserialize()
}
}
Inside the 'SupportedType' member, simply return a new enumeration of the parent type. For example the SupportedTypes member inside Person.JsonSerializer would look like this:
get { return new[] { typeof( Person ) }; }
Inside the 'Serialize' method, simply cast the obj parameter to your type, and then begin setting each property like so:
var result = new Dictionary
var person = obj as Person;
if (person == null)
return result;
result["Name"] = person.Name;
result["Age"] = person.Age;
result["Address"] = person.Address;
result["City"] = person.City;
result["State"] = person. State;
result["Zip"] = person.Zip;
result["PhoneNumbers"] = person.PhoneNumbers;
return result;
Inside 'Deserialize' do the same thing, only backwards (not covered here)... In order to take advantage of the Json data, let's initialize a PersonViewModel class. This class will be used by our View pages. Here is a quick example of what this class might look like:
class PersonViewModel
{
public PersonViewModel(Person person)
{
Person = person;
Json = string.Empty;
}
public Person Person { get; private set; }
public string Json { get; set; }
}
This class will be initialized by an Action method on our Controller class. Inside that method is where I initialize the Json property. In order to serialize our data to Json, we need to register our custom JavaScriptConverters with an instance of the JavaScriptSerializer. Let's do that now!
User calls:
http://mywebsite/Person/Edit/123
This will call the 'Edit' action on the PersonController; this will be where all of the things glue together.
public ActionResult Edit(int personID)
{
var person = _repository.GetPerson(personID);
var converters = new List
converters.Add(new Person.JsonSerializer());
converters.Add(new PhoneNumber.JsonSerializer());
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(converters);
var viewModel = new PersonViewModel(person);
viewModel.Json = serializer.Serialize(person);
return View(viewModel);
}
Inside the Edit view, we can now simply use a server tag to initialize a variable to be used by the page (in javascript notation). Here is the best part!!
var person = <%= Model.Json %>;
$(document).ready(function(){
alert(person.Name + ' is ' + person.Age + ' years old');
});
Cool huh?
3 comments:
Hey Luc,
That's an interesting approach. The way I did it in a recent ASP.NET MVC project I worked on was to add a toJson extension method to Object.
using System.Web.Script.Serialization;
namespace MyProject.Mvc.Html
{
public static class JsonHelperExtensions
{
static JavaScriptSerializer _serializer = new JavaScriptSerializer();
public static string ToJson(this object o)
{
return _serializer.Serialize(o);
}
}
}
This allowed me to do something similar to what you do in your view
var foo = <%=Model.Person.toJson()%>
Or you could do something like this
How to serialize you model to either Json, Xml or Html
You only need to add an attribute to an Action.
:)
I agree with Scott. It is an interesting approach but using standard serialization is less code and doesn't polute your data classes with serialization logic.
Post a Comment