Microsoft .Net

Returning raw JSON from Web API 2

One of the advantages of Web API is that it can encode a request based on what was requested in the header of the request. If you want JSON, you send the application/json header. If you want XML, you send the application/xml header to the server. While that's true, there are plenty of hooks along the way that you may get stuck on. This doc covers setting up a Web API service in IIS so that in can accept requests from other domains and return raw JSON. Note this info is based on Web API 2 and Visual Studio 2013.

The first thing is to start with a new Web API project. Next we need to install the Microsoft.AspNet.Cors nuget package:

Next add a reference to the System.Web.Http.Cors assembly so we can use the [EnableCors] decorator.

If hosting in IIS, add the Access-Control-Allow-Headers and Access-Control-Allow-Methods policies to the HTTP Response headers:

Once your API is running, you can run Fiddler or Firefox to see what headers are coming back from the API:

Web API code

Basically, to return raw JSON, we need to do the following:

Server code:
[EnableCors(origins:"*", headers:"*", methods:"*")] 
public class JsonController : ApiController
{
    // GET api/json
    public List <string> Get()
    {
        var json = File.ReadAllText(@"c:\users\krafty\code\JsonAPI\JsonAPI\App_Data\gems.json");

        var js = new JavaScriptSerializer();
        var obj = js.Deserialize<object>(json);
        var ser = js.Serialize(obj);

        var lst = new List<string>();
        lst.Add(ser);

        return lst;
    }
}

You could also use this if you don't want to allow everyone to access your API:
[EnableCors(origins:"http://localhost:8082", headers:"*", methods:"*")]

Client side code

On the client, we need to set the accept header. If using AngularJS, the complete call would look like this:

app.factory('GemFactory', function($http, $q){
    var factory = {};
    
    factory.getGems = function(){
        var defer = $q.defer();  

        var url = "http://mymachinename:8082/api/json";
        
        var config = {headers:  {
                'Accept': 'application/json'
            }
        };

        $http.get(url, config).success(function(json){
            defer.resolve(json);
        }).error(function(data, status, headers, config) {
            $('#status').text('No data returned from API');
        });
    
        return defer.promise;
    };
    
    return factory;
});
Note if you wanted to get back XML, your accept header would be application/xml.

To call the factory and consume the deferred promise:

app.controller('StoreController', function($scope, GemFactory){
    //code here gets executed when controller is called

    GemFactory.getGems().then(function(json){
        if($scope.store != undefined)
            $scope.store.products = $.parseJSON(json); 
    });
});

The trouble with quotes


If you're thinking JSON is just a string, and you can just return a string from your service, you'd be wrong. Strings get wrapped in quotes which screws up JSON:

The fix is to have your API method return a List of type string.