- Control over how dates get formatting (I don’t like the \/Date(123)\/ MS AJAX style)
- The ability to serialize object graphs that contain cycles (by telling Json.NET to ignore them)
“{\”Message\”:\”Hello World\”}” (double wrapped or double quoted — requires two JSON.parse() calls)
instead of this:
{“Message”:”Hello World”}
For more info regarding that problem, see the StackOverflow question I asked about it. It details how to still use Json.Net, but not have the “double quoted” or “double wrapped” json string. Unfortunately, the solution really only works for sending responses back to the client, and it also forces the use of json, so you can’t have soap endpoints to your service methods. For service methods that take object types as params, you can’t force WCF to use Json.Net to deserialize, and it will automatically use DataContractJsonSerializer. This means if your dates aren’t in MS AJAX date format, you’ll throw exceptions. So I’m ditching Json.Net in this particular app stack. Soon, I want to do an article on creating a fully equipped REST service by creating your own IHttpHandler, instead of using WCF. In that case, I think Json.Net would be the best choice for serialization and deserialization. But that post is for another time.
So, I’m back to using DataContractJsonSerializer. The big advantages to this are:
- My service methods return DTO types, not the arbitrary “Message” type (System.ServiceModel.Channels.Message), or “double wrapped” json strings.
- My service methods can take object types (DTO types, entity types, whatever) as input params, as opposed to json strings (personJsonString), which require manual deserialization within the service method
- My services can now have both REST (json) and SOAP (xml) endpoints
- With both endpoint types, the service can easily be called either directly from client code, or in code behind, using the proxy classes created with Add Service Reference
Removing Cycles (Almost) Automatically
Imagine that a Person object has an Address object, and an Address object has a list of Person objects that have that Address.somePerson.Address; someAddress.People;
This creates a cycle in our object graph.
.
Since json doesn’t support references, cycles would cause the DataContractJsonSerializer to infinitely recurse (since it can’t be simply told to ignore cycles, like a much superior serializer I know about). This just means we have to strip out cycles from our object graphs before we try to serialize them. That shouldn’t be too hard. We’ll start with a root object, and traverse all known related objects, adding each object to a flat list along the way. If we encounter an object that’s already in our running flat list, then we assign parent object’s property to null, or remove it, or assign it to a stub object, just so long as it doesn’t point to the object in question, since it’s already in our graph once. This breaks the cycle. The way I accomplished it is with a set of recursive methods in each of the DTO classes (I’m only interested in stripping cycles from DTO graphs, since that’s all I send to the client).
Here’s a reminder of what our sample model looks like.
Given this model, the code to strip cycles (with Person as the root object) is:
public partial class PersonDto
{
public PersonDto StripCycles()
{
Dictionary<object, string> graphObjs = new Dictionary<object, string>();
StripCycles(graphObjs, "");
return this;
}
internal bool StripCycles(Dictionary<object, string> graphObjs, string path)
{
if (graphObjs.ContainsKey(this))
return false;
graphObjs.Add(this, path);
// Single navigation property references
if (Address != null)
if (!Address.StripCycles(graphObjs, path + ".Address"))
Address = null;
// Collections
if (Projects != null)
for(int i = 0; i < Projects.Count; ++i)
if (!Projects[i].StripCycles(graphObjs, path + ".Projects[" + i + "]"))
Projects.RemoveAt(i--);
return true;
}
}
So we’ve got 1 public method which can be used very easily. somePerson.StripCycles(); That can be safely serialized, no matter how crazy your object graph was before. This of course requires that each DTO class also has the same 2 StripCycles() methods implemented. Each implementation is different. Each class will have logic for each navigation property, and each collection of other DTO types. The methods aren’t directly recursive; but they do all call each other. A calls B which calls A which calls B, until your “base case” is reached, which is either you end up at a leaf node of your object graph, or you encounter a cycle, and break it (which is really just turning it into a leaf node), then the calls start popping back up.
Now, since it would be quite tedious to create and maintain these methods for each DTO class (especially during initial development, where new types are often added, and existing ones are constantly modified), we’ll again leverage the T4 templating engine to create these methods for us. We have all the model’s metadata exposed to the T4 runtime, so this is pretty easy. I won’t post the code inline, since the whole template is around 400 lines. But it’s an updated version of the DtoTemplate.tt I previously uploaded. Download the project zip at the end of the post to check out the new templates.
More options when removing cycles
You may not want to just “break” the cycle. You might want some indication that the relationship exists. In the case of the drawing, sam and sam.Address.People[0] refer to the same object in memory. Well, you could assign sam.Address.People[0] to a “stub object” that gives us the info we need (like the primary key value of the real object).
// Break the cycle by replacing the circular reference with a "stub" object
sam.Address.People[0] = new PersonDto { ID = 1 };
This approach does have some additional problems though. In client script, you’ll have objects that only have their PK field populated. And you might have to try to “hunt down” the real object elsewhere in the object graph to get its other properties. Very annoying. So, in the T4 template, I provide some additional options for how cycles will be removed. If the “stub” objects are used, then each DTO type will have some additional properties, shown here.
/// <summary>
/// If true, this is not the original object. This is a placeholder that only has the ID and FK properties set.
/// The original object was removed, to prevent cycles in the object graph.
/// </summary>
[DataMember] public bool __isCycleStub { get; private set; }
/// <summary>
/// The path to the "real" object that this stub represents, from the root of the original object graph.
/// This can be resolved in javascript like this:
/// var realObj = eval("graphRoot" + stubObj.__pathFromRoot);
/// alert(realObj.someProperty);
/// </summary>
[DataMember] public string __pathFromRoot { get; private set; }
This makes the stub objects easy to find, and the real objects they represent easy to track down.
Wrapup
All in all, there are quite a few changes I’ve made to the data layer. Also, since this is my foundation strategy for new projects right now, I’ve collected all of the templates, utility classes and extension methods into their own project, so I can easily redistribute them as a group for use in multiple dependent projects. And through the glory of svn:externals, it’s easy for my dependent projects to get the latest version of all these tools. Anyway, rather than post all of the files individually, here’s the whole project:| DataLayerHelpers.zip |
The zipped project comes with the latest AutoMapper in the Lib folder, and a custom build of HyperDescriptor that works against .NET 4 (StackOverflow question concerning HyperDescriptor in .NET 4). There are also some handy singleton classes in there. I especially like the PerRequestSingleton, which creates a single instance of a class that is per request (ASP.NET-page-life-cycle-wise), and per user (it uses HttpContext.Current.Items for storage). It’s a great way to make sure you’ve always got an instance of your ObjectContext class on hand, but without having to worry about when and where you create it.
Next time I will try to get to the actual WCF REST service.
The Cake Is Not A Lie
Well, the stuff I was doing with the data layer, with a few utility classes, and the T4 templates ended up being much more useful than I thought. Useful enough that it warrants more than just a couple of blog posts with some file attachments. Also, the more I worked with WCF REST, the more I hated it. Crappy date format when you serialize to json. No control over serialization. No cycles in your object graphs. No anonymous types. An ungodly amount of configuration. Ridiculous error handling (none of it global that “just works”). So, I started to shop around, and while some people are taking to creating REST services using MVC, I haven’t drank the MVC kool-aid yet, and that’s not really what it was designed for anyway, so I wasn’t overly keen on that route. However, a plain IHttpHandler….now we’re talking. You get whatever advantages you need from the ASP.NET runtime, but all you have to do is implement ProcessRequest(), which gives you an HttpContext, which is all you really need. You have full access to the request, and you create a response. There are excellent tools like Json.NET to help you with the json serialization. You just set the content-type of the response, and away you go.
So, as our code and our approaches to problems always do, my “end to end” strategy was evolving into something much, much more. I ended up with 2 incredibly useful libraries: One for getting the Data Access Layer up and running (utility classes and T4 templates), and the other for creating RESTful services based on simple IHttpHandlers (with it’s own basic routing and processing engine). These libraries have been released on CodePlex. They are:
I have spent a very good amount of time polishing these libraries and running them through their paces, to make them production ready. I can happily say they are in use in some large, enterprise-scale applications right now. Yes, there are bound to be a few bugs here and there, but these are ready for production use, right now. I’ve also spent a very liberal amount of time creating overview pages that explain the gist of the libraries and how they work, and working examples. The examples and documentation can be found at http://restcake.net.
These are very small, unobtrusive libraries. Nothing enormous and overreaching. Read the RestCake overview page and the Loef overview page to get a feeling for these libraries and what they offer. You’ll see what I mean. If you have any issues or suggestions, please use the CodePlex pages to report them, and I’ll try to get on them right away. For now, I’m going to continue to improve the documentation and working examples, and iron out any bugs as they surface. As my good friend Jerry would say, “I’m just one man”.
Enjoy these new libraries! The cake is not a lie!