1

I've never had to do an API call before and I've been trying but so far unsuccessful and I think getting myself even more confused :/ .

Basically what I'm trying to do is a get call passing in a username to get back the SYSID of the user, then using the SYSID in a post call to create a support ticket for the user. Service now is the ticketing system being used

I have managed to successfully do it in powershell using the sample code provided with some slight modifications as below:

$user = "TestLogin"
$pass = "TestPassword"
$QueryUser = "TestUser"
$description = "Test description"
$title = "Test title"

# Build auth header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $pass)))

# Set proper headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))
$headers.Add('Accept','application/json')

# Specify endpoint uri
$uri = "https://TestURL.com/api/Test/table/sys_user?sysparm_query=user_name=" + $QueryUser + "&sysparm_fields=sys_id"
# Specify HTTP method
$method = "get"

{request.body ? "$body = \"" :"""}

# Send HTTP request
$response = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri

#Removes {"result":[{"sys_id":" off the start of the response string
$response = $response -replace ".*"":"""
#Removes "}]} off the end of the response string
$SYSID = $response -replace """}]}*."

# Print response
write-host $SYSID


# Set proper headers
$headers.Add('Content-Type','application/json')

# Specify endpoint uri
$uri = "https://TestURL.com/api/Test/table/new_call"

# Specify HTTP method
$method = "post"

# Specify request body
$body = @{
            caller= $SYSID
            description= $description
            short_description= $title + " - " + $QueryUser
         }
$bodyJson = $body | ConvertTo-Json

# Send HTTP request
$response = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri -Body $bodyJson

# Print response
$response.RawContent

The latest code I've used is below followed by the error I'm getting (some of it is commented out but that was just me trying different things to try get it to function) This portion is just the get call: (Note: the below is just the get portion, I havent really tried the post yet to create the ticket)

public string Get(string QueryUsername)
        {    

    string username = "TestLogin";
    string password = "TestPassword";
    string url = "https://TestURL.com/api/Test/table/sys_user?sysparm_query=user_name=" + QueryUsername + "&sysparm_fields=sys_id";

    var auth = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(username + ":" + password));
    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    request.Headers.Add("Authorization", auth);
    string method = "get";
    string SYSID = "";

    //using (var streamWriter = new StreamWriter(request.GetRequestStream()))
    //{
    //    string json = JsonConvert.SerializeObject(new
    //    {
    //        User_name = QueryUsername
    //    });

    //    streamWriter.Write(json);
    //}

    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
    {
        var res = new StreamReader(response.GetResponseStream()).ReadToEnd();

        JObject joResponse = JObject.Parse(res.ToString());
        JObject ojObject = (JObject)joResponse["result"];
        string callNumber = ((JValue)ojObject.SelectToken("number")).Value.ToString();

        return (res.ToString());
    };
}

Current error:

System.InvalidCastException: 'Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'Newtonsoft.Json.Linq.JObject'.'

Error is occuring at line 53:

JObject ojObject = (JObject)joResponse["result"];

Debugger output of variables: enter image description here

I've been trying and reading watching tutorials but have not really progressed and decided it's time to reach out for some help.

Any assistance or links to tutorials that might help me out would be greatly appreciated

Andy Bruce
  • 33
  • 3
  • Have you used the debugger to see what the value of joResponse is? If it is an array, you have to loop through its elements and cast those that are not arrays to Jobjects. – Jawad Jan 16 '20 at 02:36
  • Does this answer your question? [Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray'](https://stackoverflow.com/questions/33495634/unable-to-cast-object-of-type-newtonsoft-json-linq-jobject-to-type-newtonsoft) – Murchiad Jan 16 '20 at 02:39
  • You need to get the body of the response not the full response ... – Soumen Mukherjee Jan 16 '20 at 02:39
  • Your JSON string is an array rather than an object, so try casting the response to a JArray rather than a JObject. – Murchiad Jan 16 '20 at 02:42
  • I've added the output from the debugger which does get the ID I guess I'm just not getting the ID out so I'm further than I thought – Andy Bruce Jan 16 '20 at 03:33

3 Answers3

1

Trying to make a class and deserialize it using

public class Result
{
     public string Number {get; set;}
     .
     .
     .
}

.
.
.

//in your "Get" method change the return for the class type
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    var res = new StreamReader(response.GetResponseStream()).ReadToEnd();

    return JsonConvert.DeserializeObject<Result>(res);
};

.
.
.

//if you need to get 'callNumber'
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    var res = new StreamReader(response.GetResponseStream()).ReadToEnd();

    var obj = JsonConvert.DeserializeObject<Result>(res);

    var callNumber = obj.Number;

    return obj;
};
0

If your response looks something like follows

{
   ....,
   ....,

   "result":
   {
      "number": 001230123,
      ....
      ....
   },

   ....
   ....
}

The following code will work.

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        var res = new StreamReader(response.GetResponseStream()).ReadToEnd();
        var dataObj = JsonConvert.DeserializeObject<dynamic>(res.ToString());

        try
        {
            var resultObj = dataObj["result"].Value;
            string callNumber = resultObj["number"].Value.ToString();
        }
        catch
        {
            // Handle your exceptions here
        }

        return (res.ToString());
    }
};
Supun De Silva
  • 1,437
  • 9
  • 15
0

Below is the code that I've managed toget working to return just the number from the JSON response

public class Result
    {
        public string sys_id { get; set; }
    }

    public class RootObject
    {
        public List<Result> result { get; set; }
    }




using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {

                var res = new StreamReader(response.GetResponseStream()).ReadToEnd();
                RootObject datalist = JsonConvert.DeserializeObject<RootObject>(res);

                if (datalist.result != null && datalist.result.Count > 0)
                {
                    var data = datalist.result[0];
                    UserSysID = "";
                    UserSysID = data.sys_id;
                    return data.sys_id;
                }
                return null;
            }
        }
Andy Bruce
  • 33
  • 3