0

I am trying to create a web API which calls the other service and returns a array of response. The called service returns the response. I am able to get the individual item from the called service. But not sure how to build array of items and return as response from the API I am creating.

The JSON returned from the service looks like

{
"cr_response": {
    "details": [{
        "name": "Req",
        "fields": [{
                "value": "Prj0\r\nPrj1",
                "name": "Project"
            },
            {
                "value": "October 13, 2017 14:18",
                "name": "Submitted"
            },
            {
                "value": "John",
                "name": "Rec Name"
            }
        ]
    }],
    "cr_metadata": {}
}
}

And the POCO class looks like

public class Field
{
    public string value { get; set; }
    public string name { get; set; }
}

public class Detail
{
    public string name { get; set; }
    public List<Field> fields { get; set; }
}

public class CrMetadata
{
}

public class CrResponse
{
    public List<Detail> details { get; set; }
    public CrMetadata cr_metadata { get; set; }
}

 public class RootObject
 {
      public CrResponse cr_response { get; set; }
 }

Below is the code for calling the service and retrieving the response from the services

var response = await iLab_client.GetAsync(uri);
var datafile = await response.Content.ReadAsStringAsync();
var returnDataObj = JsonConvert.DeserializeObject<DTO.RootObject>(datafile);

foreach (var form in returnDataObj.cr_response.details)
{
    name_response = form.name;
    return Ok(name_response);
}

Here I can access the name from the details but not sure how can I access the all the name and value from the fields and construct it in a array. And send it as a JSON response. I tried like

            foreach (var form in returnDataObj.cr_response.details)
            {
                var id_response = form.fields;
                return Ok(id_response);
            }

But it throws error like

<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content 
type 'application/xml; charset=utf-8'.
</ExceptionMessage>

System.InvalidOperationException

xyz
  • 531
  • 1
  • 10
  • 31
  • I notice that the error message specifically mentions the content type `application/xml`. Valid XML requires there to be a single root node. It's possible that the returned object cannot be a collection. If you can change the client to request JSON instead, that might fix the problem. Otherwise, you might do well to return an object with the array as one of its properties instead of returning the array directly. – StriplingWarrior Oct 19 '17 at 17:55
  • @StriplingWarrior Are you asking to change instead of HttpClient? – xyz Oct 19 '17 at 18:11
  • No. Your code is both *consuming* a web service (`ilab_client.GetAsync(...)`) and *being consumed by* a client (`return Ok(...);`). The client that is consuming your Web API endpoint is sending an HTTP request. Web API is looking at the request and thinking that it needs to serialize the response as XML rather than JSON. That may be due to a header (or absence of a header) on the web request. Or it could be due to [the way your Web API application is configured](https://stackoverflow.com/q/12629144/120955). Or some combination of those two. – StriplingWarrior Oct 19 '17 at 18:45

1 Answers1

0

To return array from Web API you need to fill your array and return it outside foreach loop:

var list = new List<string>();
foreach (...){
    var name = ... 
    list.Add(name);
}
 return Ok(list.ToArray()); // or just   return Ok(list); 

This is how to deserialize JSON to POCO and get the list of the names:

[TestMethod]
public void TestJsonToPocoAndGetNames()
{
    const string Json = @"
        {
        ""cr_response"": {
            ""details"": [{
                ""name"": ""Req"",
                ""fields"": [{
                        ""value"": ""Prj0\r\nPrj1"",
                        ""name"": ""Project""
                    },
                    {
                        ""value"": ""October 13, 2017 14:18"",
                        ""name"": ""Submitted""
                    },
                    {
                        ""value"": ""John"",
                        ""name"": ""Rec Name""
                    }
                ]
            }],
            ""cr_metadata"": {}
        }
    }
    ";

    var settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
    };
    var response = JsonConvert.DeserializeObject<RootJsonObject>(Json, settings);

    var names = new List<string>();
    foreach (var detail in response.CrResponse.Details)
    {
        names.Add(detail.Name);

        foreach (var field in detail.Fields)
        {
            names.Add(field.Name);
        }
    }

    Assert.AreEqual(
        "Req, Project, Submitted, Rec Name",
        string.Join(", ", names.ToArray()));
}

POCO classes:

public class RootJsonObject
{
    [JsonProperty("cr_response")]
    public CrResponse CrResponse { get; set; }
}

public class CrResponse
{
    [JsonProperty("cr_metadata")]
    public CrMetadata CrMetadata { get; set; }

    [JsonProperty("details")]
    public Detail[] Details { get; set; }
}

public class CrMetadata
{
}

public class Detail
{
    [JsonProperty("fields")]
    public Field[] Fields { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

public class Field
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("value")]
    public string Value { get; set; }
}
Dmitry Pavlov
  • 30,789
  • 8
  • 97
  • 121
  • We have name in both the details as well as in the fields. I want to get the name and value from fields. – xyz Oct 19 '17 at 17:48
  • To access JSON data (without deserializing them into POCO classes) you might want to check this https://stackoverflow.com/questions/6620165/how-can-i-parse-json-with-c/17842600#17842600 – Dmitry Pavlov Oct 19 '17 at 17:49
  • Using POCO cant I access to the name and values under fileds? – xyz Oct 19 '17 at 17:51
  • I tried `form.fields.Children() it throws error like ` doesnot contain a definition for 'Children'` – xyz Oct 19 '17 at 18:00
  • I also tried `names.Add(form.fields.name)` even that doesnt work – xyz Oct 19 '17 at 18:02
  • As for Children - it is available when you deserialize using Newtonsoft.Json; fields should be used as JArray – Dmitry Pavlov Oct 19 '17 at 18:03
  • I am using the `Newtonsoft.Json` and using the this code `JsonConvert.DeserializeObject(datafile)` – xyz Oct 19 '17 at 18:05
  • @xyz it seems you can't put all things together yourself. So I have updated the code to show you how to do it. Hope that helps – Dmitry Pavlov Oct 20 '17 at 09:25