Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IHttpActionResult with JSON string

Tags:

json

c#

json.net

I have a method that originally returned an HttpResponseMessage and I'd like to convert this to return IHttpActionResult.

My problem is the current code is using JSON.Net to serialize a complex generic tree structure, which it does well using a custom JsonConverter I wrote (the code is working fine).

Here's what it returns:

    string json = NodeToJson(personNode);

    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(json, Encoding.UTF8, "application/json");

    return response;

The NodeToJson method is where the custom converter comes into play ...

private static string NodeToJson(Node<Person> personNode) {

    var settings = new JsonSerializerSettings {
        Converters = new List<JsonConverter> { new OrgChartConverter() },
        Formatting = Formatting.Indented
    };

    return JsonConvert.SerializeObject(personNode, settings);

}

Note this returns a string, formatted as JSON.

If I switch this to IHttpActionResult, it seems to fail regardless of what I try. I can just leave it (it works) but I am supposed to be using best practices for this and IHttpActionResult seems to be what I should be using.

I have tried to return Json(json); but this results in invalid, unparsable JSON, presumably because it's trying to do a double conversion?

return Ok(json); results in the JSON string being wrapped in XML.

What is the right way to do this?

EDIT:

I have successfully converted every method in this project to use IHttpActionResult now except this particular method.

It's a serialization of a generic tree to JSON. Regardless of what approach I try, I get back invalid JSON. The HttpResponseMsessage approach works fine, but I can not get valid JSON back with IHttpActionResult.

like image 382
Patrick Avatar asked Mar 26 '16 21:03

Patrick


People also ask

What is the difference between IHttpActionResult and HttpResponseMessage?

IHttpActionResult contains a single method, ExecuteAsync, which asynchronously creates an HttpResponseMessage instance. If a controller action returns an IHttpActionResult, Web API calls the ExecuteAsync method to create an HttpResponseMessage. Then it converts the HttpResponseMessage into an HTTP response message.

Is there a JSON data type in Java?

It is a high-level API that provides immutable object models for JSON object and array structures. These JSON structures are represented as object models using the Java types JsonObject and JsonArray .


2 Answers

You can create your own IHttpActionResult class instance to return the JSON and a method in your controller or base controller class to utilize it.

Create the IHttpActionResult instance that sets the content and status code:

public class JsonTextActionResult : IHttpActionResult
{
    public HttpRequestMessage Request { get; }

    public string JsonText { get; }

    public JsonTextActionResult(HttpRequestMessage request, string jsonText)
    {
        Request = request;
        JsonText = jsonText;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(Execute());
    }

    public HttpResponseMessage Execute()
    {
        var response = this.Request.CreateResponse(HttpStatusCode.OK);
        response.Content = new StringContent(JsonText, Encoding.UTF8, "application/json");

        return response;
    }
}

Add a method to your controller to create the result. Here is a Web API example:

public class MyApiController : ApiController
{
    protected internal virtual JsonTextActionResult JsonText(string jsonText)
    {
        return new JsonTextActionResult(Request, jsonText);
    }

    [HttpGet]
    public IHttpActionResult GetJson()
    {
        string json = GetSomeJsonText();
        return JsonText(json);
    }
}
like image 107
TGRA Avatar answered Nov 10 '22 01:11

TGRA


Another recommendation is as below;

var json = JToken.FromObject(yourObject);
return Ok(json);
like image 23
Youngjae Avatar answered Nov 10 '22 01:11

Youngjae