0

I am getting this error when trying to call Post Contacts endpoint:

{\r\n "ErrorNumber": 14,\r\n "Type": "PostDataInvalidException",\r\n "Message": "Invalid Json data"\r\n}

This is my JSON:

{
  "Contacts": [
    {
      "Name": "Delia Du Toit",
      "ContactNumber": "2010080871087",
      "AccountNumber": "2222",
      "ContactStatus": "ACTIVE",
      "FirstName": "Delia",
      "LastName": "Du Toit",
      "CompanyNumber": "123456789",
      "EmailAddress": "myemail@gmail.com",
      "SkypeUserName": "",
      "Addresses": [
        {
          "AddressType": "STREET",
          "AddressLine1": "1 Du Bois",
          "AddressLine2": "  ",
          "AddressLine3": "",
          "AddressLine4": "",
          "City": "Brakpan",
          "PostalCode": "1540",
          "Country": "South Africa",
          "Region": "Gauteng"
        },
        {
          "AddressType": "POBOX",
          "AddressLine1": "",
          "AddressLine2": "",
          "AddressLine3": "",
          "AddressLine4": "",
          "City": "",
          "PostalCode": "",
          "Country": "",
          "Region": ""
        }
      ],
      "Phones": [
        {
          "PhoneType": "DDI",
          "PhoneNumber": " 011 852 2589",
          "PhoneAreaCode": "",
          "PhoneCountryCode": "+27"
        }
      ],
      "IsCustomer": true,
      "DefaultCurrency": "ZAR"
    }
  ]
}

This is my function:


public static async Task<string> SaveContact(string tenant_id, string contact)
        {
            string result = "";
            string url = "https://api.xero.com/api.xro/2.0/contacts";
            string key = string.Format("Bearer {0}", Token);

            var client = new RestClient(url);
            var request = new RestRequest("/", Method.Post) { AlwaysMultipartFormData = true };
            request.AddHeader("authorization", key);
            request.AddHeader("Xero-tenant-id", tenant_id);
            request.AddHeader("content-type", "application/json");
            request.AddBody(contact, "application/json");

            var response = await client.ExecuteAsync(request);

            result = response.Content;

            if(response.StatusCode == HttpStatusCode.OK)
            {
                return "OK";
            }

            return result;
        }

Not sure what is wrong. Not sure where to start looking either since my Json appears correct and the error appears to be very generic? Could someone shed some light on this please?

Thanks

zdb
  • 65
  • 1
  • 1
  • 10
  • can you try cutting your request down to the minimum (I think just the name for creating a new contact?) and see if it still fails to create? does a contact with that name already exist? – TZHX Jul 12 '22 at 12:55
  • Thanks TZHX, the problem was with the Execute call. var response = await client.ExecuteAsync(request.AddJsonBody(contact)); – zdb Jul 12 '22 at 13:28

2 Answers2

0

Okay it appears my syntax was slightly wrong with my RestClient:

public static async Task<string> SaveContact(string tenant_id, string contact)
        {
            string result = "";
            string url = "https://api.xero.com/api.xro/2.0/contacts";
            string key = string.Format("Bearer {0}", Token);

            //Trust all certificates
            System.Net.ServicePointManager.ServerCertificateValidationCallback =
                ((sender, certificate, chain, sslPolicyErrors) => true);

            // trust sender
            System.Net.ServicePointManager.ServerCertificateValidationCallback
                            = ((sender, cert, chain, errors) => cert.Subject.Contains(serverhost));

            // validate cert by calling a function
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

            var client = new RestClient(url);
            var request = new RestRequest("/", Method.Post);
            request.AddHeader("authorization", key);
            request.AddHeader("Xero-tenant-id", tenant_id);
            var response = await client.ExecuteAsync(request.AddJsonBody(contact));

            result = response.Content;

            if(response.StatusCode == HttpStatusCode.OK)
            {
                return "OK";
            }

            return result;
        }
zdb
  • 65
  • 1
  • 1
  • 10
0

It could be that in this line, contact should be the object that you want to serialize to JSON, not the JSON string. If you pass in the object, RestSharp will do the serialization for you.

request.AddJsonBody(contact)

Another possibility

I've got a very similar issue that has only started happening since we updated our RestSharp library. My issue is slightly related, but also different in that I'm getting a similar error when deserializing the response JSON, whereas you seem to be getting it when sending.

It is related to the JSON serializer that RestSharp uses (System.Text.Json, see here ) doesn't support anything other than string values.

From here

System.Text.Json doesn’t deserialize non-string values like Int, Boolean and other primitives into string properties.

System.Text.Json.JsonException: ‘The JSON value could not be converted to System.String

Any non-string value conversion produces above JsonException

So the problem in your JSON is likely to be this:

"IsCustomer": true,

One option is to change the JSON to: "IsCustomer": "true",

Or use a different serializer.

Dave B 84
  • 568
  • 1
  • 5
  • 14
  • "IsCustomer" carries the following note in the API documentation: "Cannot be set via PUT or POST - it is automatically set when an accounts receivable invoice is generated against this contact." I don't know whether it would throw an error if you try to specify it, or just ignore it. – droopsnoot Jul 13 '22 at 11:17