In my last episode with MVC, I was trying to reconcile MVC 5.0 with WebAPI 5.1 and the fact that the former used a broken JSON library, while the latter used the better Newtonsoft JSON library. I implemented a model binder and a value provider factory to get the two projects in sync, and all was right with the world.
As the project has gone on, we've come across instances where we've needed to call MVC controllers and get JSON responses back. We have created WebAPI controllers in some cases, but the way the project is structured, we've needed to post MVC models as JSON via AJAX back to MVC methods where we cannot reference them in the WebAPI project (otherwise we'd have a circular reference).
There are probably a few ways to restructure this to work. Ripping the view models out to a library that can be referenced by both MVC and WebAPI was one idea, for instance. But that would've been a lot of work and caused bigger deployment headaches that I don't want to get into here. (A smaller project might've gotten away with it, though.)
Returning JSON to the client is almost as easy as having your MVC controller return a JsonResult — the MVC Controller class has its own built-in Json() method to do just that. Except, of course, it uses the JSON serializer we never want to see again. In this case, I created my own JsonNetResult class (based on a StackOverflow question, naturally), and my controller just calls
this.JsonNetResult(resultObj); to do the magic.
I considered leaving it here, so that we would have to decorate every JSON method with this handler as well as specifying it returned a JsonNetResult (unless there's a way to find out programmatically in the filter whether the current controller method returns a JsonNetResult, but I failed to find that); but ultimately, I decided to just override the default error handler site-wide (since it falls back to the base class for non-JSON requests, it shouldn't be an issue). That was done by editing the MVC app's RegisterGlobalFilters method to read:
Now, whenever we want to return an exception back to a JSON request, all we have to do is throw an exception:
Processing the return message in jQuery is left as an exercise to the reader (though if you use WebAPI, you probably already know). ;)