Reputation: 1505
I've written a simple API which is reading a json file and providing this data via GET. My model for the controller looks like this:
public static class ServerListHandler
{
private static readonly string _serverListPath;
private static FileSystemWatcher _serverListWatcher;
private static string _servers;
public static string Servers
{
get
{
if(_serverListWatcher == null && File.Exists(_serverListPath))
{
InitializeFileWatcher();
ReadData();
}
return _servers;
}
private set
{
_servers = value;
}
}
static ServerListHandler()
{
_serverListPath = Properties.Settings.Default.ServerListPath;
if(!File.Exists(_serverListPath))
{
Debug.WriteLine("Could not find config with path: " + _serverListPath);
}
else
{
ReadData();
InitializeFileWatcher();
}
}
private static void InitializeFileWatcher()
{
_serverListWatcher = new FileSystemWatcher(Path.GetDirectoryName(_serverListPath));
_serverListWatcher.EnableRaisingEvents = true;
_serverListWatcher.Deleted += OnServerListChanged;
_serverListWatcher.Changed += OnServerListChanged;
_serverListWatcher.Created += OnServerListChanged;
_serverListWatcher.Renamed += OnServerListChanged;
}
private static void OnServerListChanged(object sender, FileSystemEventArgs e)
{
ReadData();
}
private static void ReadData()
{
try
{
string content = File.ReadAllText(_serverListPath);
Servers = content;
}
catch(Exception ex)
{
Debug.WriteLine("Could not read server file: " + ex);
}
}
}
I added this line in WebApiConfig.cs
to get a json output
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
The original json file looks like this:
[
{
"Name": "testing",
"IP": "127.0.0.1"
}
]
And the GET result is:
"[\r\n {\r\n \"Name\": \"testing\",\r\n \"IP\": \"127.0.0.1\"\r\n }\r\n]\r\n"
Of course the result is not parsable for Json.NET. Now my question is if I have to parse the json string manually that it fits or if I just forgot to enable/check something to enable a proper json output.
Edit
As requested this is my controller
public class ServersController : ApiController
{
public HttpResponseMessage GetAllServers()
{
if(ServerListHandler.Servers == null)
return Request.CreateResponse(HttpStatusCode.NoContent);
return Request.CreateResponse(HttpStatusCode.OK, ServerListHandler.Servers);
}
}
Upvotes: 1
Views: 512
Reputation: 129697
The problem here is that Web API assumes by default that it is responsible for serializing anything you give it. For most use cases, this is exactly what you would want. But if your content is already JSON, Web API has no way of knowing that; it will happily re-serialize the string, adding extra quotes and backslashes in the process.
To return a JSON string untouched, you need to explicitly create the response content object (rather than letting Web API create it), making sure to set the media type to so that downstream clients will still interpret it as JSON (rather than plain text). Here is the revised controller method:
public HttpResponseMessage GetAllServers()
{
if(ServerListHandler.Servers == null)
return Request.CreateResponse(HttpStatusCode.NoContent);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(ServerListHandler.Servers, Encoding.UTF8, "application/json");
return response;
}
Another possible (but less efficient) solution is to deserialize your JSON to an object, then return that object from your controller method, as was suggested by @CathalMF in the comments. Web API will then re-serialize the object back to JSON again when it creates the response.
Upvotes: 2