For various reasons you may find that the default JsonResult returned by invoking the controller method such as
Is unsuitable for the consumer. The main issue most often encountered is that this method uses the JsonResult which in turn uses the
This means that you can provide that serializer a parameter specifying you own custom type resolver.
Other issues, such as maximum recursion depth and maximum length and type resolvers can be simply configured in web.config. See Configuring JSON Serialization section on MSDN.
Back to the core problem though.
To override the
JsonResult, we would need to do 2 things:
- Create our own custom JsonResult implementation
- Tell the controller to use ours rather than the stock one.
JsonResult is needed because the base one hard codes the construction of the
So here we go. Some CTRL+C, CTRL+V later from the open source MVC on Codeplex gives us
Next, we want to our controller(s) an easy way to choose our TypedJsonResult rather than the stock one. Luckily, the controller boils down the call
Json(data) and several other signatures to a call to a virtual signature which we may simply override, like so:
That’s it! On line 3 you will notice we return our custom Typed
JsonResult, whereas the stock implementation would have returned the JsonResult.
If this new behavior is desired everywhere, then you would probably want to place this override in a base controller of your own, and have all your controllers inherit it.
Other powers this bestows on you is of course using some other serializer altogether, such as Json.NET or whatever you fancy.
Now back to my own type resolver. You could, after all, use the
SimpleTypeResolver built into the framework, which works quite well. However, it introduces fairly long type names – frowned upon by my clients consuming this Json on other platforms, and also doesn’t enable me to map my own type names to a type of my choice. Enter the
This resolver spelunks specific assemblies only (those named [whatever].ValueObjects which are my naming convention for POCO public objects) and catalogs them into a dictionary by short type name.
It doesn’t know how to resolve 2 types of the same name if they only differ by namespace, but then again I’d ask “how come you would define 2 classes of the same exact name in your solution?” You can define type names to whatever suites your needs.
The resolver’s responsibility is twofold: Given a string , return the System.Type that corresponds to it. Given a type, return a name for it. The former is used during deserialization, the latter when serializing.
Now you may not need or like this particular type resolver implementation. But now that you can inject your own, possibilities are limitless. These can range to configuration based type resolution, versioning decisions base on some revision upgrades etc.
Note also that upon deserialization, the type resolver is only called when a type discriminator exists in the JSON stream. That is, a complex type that doesn’t contain “__type”:”foo” will be serialized by the
Hopefully, this helps you, or me-of-the-future when the gray cells got filled with the next great thing..