How to return a Json object from a C# method

118,021

Solution 1

resp is already a JSON string, but it is not valid JSON (the keys are not wrapped in quotes ("). If it is returned to angular, the JavaScript JSON.parse() method is unable to deserialize it. However, you can use JSON.NET in deserialize it to a JObject and serialize it again into valid JSON and create your own HttpResponseMessage...

public HttpResponseMessage Get()
{
    string userid = UrlUtil.getParam(this, "userid", "");
    string pwd    = UrlUtil.getParam(this, "pwd", "" );

    string resp = DynAggrClientAPI.openSession(userid, pwd);
    var jObject = JObject.Parse(resp);

    var response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
    return response;
}

Or you can just return the JObject and have Web API serialize it for you...

public JObject Get()
{
    string userid = UrlUtil.getParam(this, "userid", "");
    string pwd    = UrlUtil.getParam(this, "pwd", "" );

    string resp = DynAggrClientAPI.openSession(userid, pwd);
    var jObject = JObject.Parse(resp);

    return jObject;
}

In either case, the Web API call should return this JSON, which is now valid...

{
  "status": "SUCCESS",
  "data": [
    "4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d"
  ]
}

In the angular code, you'd have to dig out the session id which is stored in an array called data...

userService.openUserSession(rzEnvJson).then(function (response) {
    var sessionResponse = response.data; // or simply response, depending if this is a promise returned from $http
    $rootScope.rgSessionVars.sessionID = sessionResponse.data[0];
});

Solution 2

The key to what is going on here is in the comment made by Mike Cheel; serialization is happening twice, once in the OP's code and once by Asp.Net WebAPI. That is why a string is returned instead of a Json object.

I was encountering the exact same thing. Here is a hello world example showing the problem. I first did something like this:

[Route("getall")]
public string GetAllItems()
{
    var result = new
    {
        x = "hello",
        y = "world"
    };
    return JsonConvert.SerializeObject(result);
}

I then tried to so something like this, thinking that I needed to return IHttpActionResult to resolve this:

[Route("getall")]
public IHttpActionResult GetAllItems()
{
    var result = new
    {
        x = "hello",
        y = "world"
    };
    return Ok(JsonConvert.SerializeObject(result));
}

Both these controller actions gave me a string rather than the Json object that I was wanting; so I go this:

"{\"x\":\"hello\",\"y\":\"world\"}"

Finally I saw the comment by Mike and realized that I needed to return the .Net object directly and just let WebAPI handle the serialization. So instead of returning this:

return Ok(JsonConvert.SerializeObject(result));

return this:

return Ok(result);

Then I got the result that I was expecting:

{"x":"hello","y":"world"}

Solution 3

I don't see what this has to do with AngularJS, but your problem is simple. Your data object is JSON encoded. So you could almost certainly access data.JsonRequestBehavior and it would be 1. But your Data field inside it is AGAIN JSON-encoded. You need to decode it before trying to use it - it's just a string when you get to this callback:

var myData = angular.fromJson(data.Data);
console.log(myData.data);

Note that your data.Data object is itself another wrapper - an array. You almost certainly want myData.data[0] to go into that sessionID field...

Share:
118,021

Related videos on Youtube

bob.mazzo
Author by

bob.mazzo

Front-end Developer with full stack experience in c# and Sql Server, working in norther NJ. Current technologies include Angular, Html/JavaScript/CSS, Kendo UI, Angular-Material, Web Api. I'm married with two boys, play piano at church, and do some gigs on the side. I love soccer (Brazil, Man City) - and enjoying training with my kids, and playing with the guys at work. [email protected]

Updated on August 24, 2021

Comments

  • bob.mazzo
    bob.mazzo over 2 years

    I am trying to fix an ASP.NET WebAPI method where a Json response is required. However it's returning a string instead.

    Initially it was returing XML format, but I've added this line to the mvc code in App_Start\WebApiConfig.cs in order to return Json by default.

    config.Formatters.Remove(config.Formatters.XmlFormatter);
    

    We've updated the c# method as follows to use NewtonSoft:

    public string Get()
    {
        string userid = UrlUtil.getParam(this, "userid", "");
        string pwd = UrlUtil.getParam(this, "pwd", "");
        string resp = DynAggrClientAPI.openSession(userid, pwd);
    
        JsonSerializer ser = new JsonSerializer();
        string jsonresp = JsonConvert.SerializeObject(resp);
    
        return resp;
    }
    

    The resp var is coming back as a string type:

    "{status:\"SUCCESS\",data:[\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\"]}"
    

    and jsonresp var looks like this :

    "\"{status:\\\"SUCCESS\\\",data:[\\\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\\\"]}\""
    

    and in Chrome's F12 dev tools, the data object is :

    ""{status:\"SUCCESS\",data:[\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\"]}""
    

    and in Console tools, the result of angular.fromJson(data) :

    "{status:"SUCCESS",data:["4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d"]}"
    

    I would appreciate some advice on how to properly return the Json object, and NOT in any string type.


    UPDATE

    By intercepting the resp var, and using Mr. Chu's suggestion below, I can successfully achieve a nice clean Json object on the client. The key is that resp needs to contains double quotes around both key:value pairs:

    public HttpResponseMessage Get()
    {
        string userid = UrlUtil.getParam(this, "userid", "");
        string pwd = UrlUtil.getParam(this, "pwd", "");
        string resp = DynAggrClientAPI.openSession(userid, pwd);
    
        resp = "{\"status\":\"SUCCESS\",\"data\":[\"194f66366a6dee8738428bf1d730691a9babb77920ec9dfa06cf\"]}";  // TEST !!!!!           
    
        var response = Request.CreateResponse(HttpStatusCode.OK);
        response.Content = new StringContent(resp, System.Text.Encoding.UTF8, "application/json");
        return response;
    }
    

    in Chrome console, the response is :

    Object {status: "SUCCESS", data: Array[1]}
    data: Array[1]
    status: "SUCCESS"
    __proto__: Object
    
    • Anthony Chu
      Anthony Chu almost 10 years
      What is resp? Is it a JSON string?
    • Mike Cheel
      Mike Cheel almost 10 years
      WebApi will convert it to JSON for you automatically (assuming you have it set up properly). Don't convert it to JSON and try just returning the C# object.
  • Chad Robinson
    Chad Robinson almost 10 years
    PS, this is all probably happening because you're doing string resp = DynAggrClientAPI.openSession( userid, pwd ); and taking the result as a string. You didn't include code for it, but if you have this return a real object, your JSON encoder can probably avoid the double-encoding and let you skip the step above.
  • bob.mazzo
    bob.mazzo almost 10 years
    I've updated my original post to show the change - now using NewtonSoft's JsonConvert.SerializeObject.
  • Anthony Chu
    Anthony Chu almost 10 years
    Have you tried this answer? Seems like it should do what you want.
  • bob.mazzo
    bob.mazzo almost 10 years
    I'm getting a front end error: "SyntaxError: Unexpected token s at Object.parse (native)"
  • bob.mazzo
    bob.mazzo almost 10 years
    the 'resp' var is indeed the source of contention here. It's a C++ program that return this. I will need that coder to return some kind of Json-formatted object, I assume.
  • bob.mazzo
    bob.mazzo almost 10 years
    we've updated the code to use JsonSerializer(). My data result is now coming back as ""{status:\"SUCCESS\",data:[\"9f9502cd3e0a81cab3b2c7b4fc6539‌​5b0b40741130c7aead49‌​8a\"]}""
  • bob.mazzo
    bob.mazzo almost 10 years
    in the meantime, I'm pulling out the data: field by first applying JSON.parse(data) then using the .split() function to access the data: field. It's not ideal, but works in the meantime.
  • Anthony Chu
    Anthony Chu almost 10 years
    It looks like resp contains invalid JSON. status and data should be wrapped in "s. The s that the error is complaining about is the s in status.
  • Anthony Chu
    Anthony Chu almost 10 years
    @bob I've updated my answer to show how you can use JSON.NET to convert the invalid JSON from DynAggrClientAPI.openSession into valid JSON and return it to Angular.
  • bob.mazzo
    bob.mazzo almost 10 years
    I've updated my original post to reflect your new code, as well as manually intercepting the resp var which re-formats the string with double quotes. My c++ guy will fix that part.
  • bob.mazzo
    bob.mazzo almost 10 years
    anthony, I've also tried your JObject idea, and it also works like a charm against the invalid Json string.
  • Harshal
    Harshal over 7 years
    public JObject Get() methods works for me, Thank you so much
  • StackOverflowUser
    StackOverflowUser about 4 years
    I know you found that return Ok(JsonConvert.SerializeObject(result)); was causing an issue. I'm just glad you posted that code because that code was what SOLVED the issue I was having.