0

I have been trying for a few days to find this issue, perhaps I am missing something.

I followed the recommendations from Microsoft when I built my sample application based on GitHub: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1

Unfortunately it seems this code does not work for what appears to be a multidimensional array.

The hope of my application is to get information from our Teamwork Desk account so we can create reporting with an ASP.NET application.

Any tips or ideas on how to get this working would be great.

Here is my code:

Folder (Models.TeamworkDesk) | Customer.cs

using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace Vanilla.Models.TeamworkDesk
{
    public class Contact
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("value")]
        public string Value { get; set; }

        [JsonPropertyName("type")]
        public string Type { get; set; }

        [JsonPropertyName("isMain")]
        public bool IsMain { get; set; }

        [JsonPropertyName("createdAt")]
        public DateTime CreatedAt { get; set; }
    }

    public class Customer
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("timezoneId")]
        public int TimezoneId { get; set; }

        [JsonPropertyName("avatarURL")]
        public string AvatarURL { get; set; }

        [JsonPropertyName("email")]
        public string Email { get; set; }

        [JsonPropertyName("contacts")]
        public List<Contact> Contacts { get; set; }

        [JsonPropertyName("externalId")]
        public string ExternalId { get; set; }

        [JsonPropertyName("extraData")]
        public string ExtraData { get; set; }

        [JsonPropertyName("firstName")]
        public string FirstName { get; set; }

        [JsonPropertyName("jobTitle")]
        public string JobTitle { get; set; }

        [JsonPropertyName("language")]
        public string Language { get; set; }

        [JsonPropertyName("lastName")]
        public string LastName { get; set; }

        [JsonPropertyName("address")]
        public string Address { get; set; }

        [JsonPropertyName("mobile")]
        public string Mobile { get; set; }

        [JsonPropertyName("notes")]
        public string Notes { get; set; }

        [JsonPropertyName("organization")]
        public string Organization { get; set; }

        [JsonPropertyName("phone")]
        public string Phone { get; set; }

        [JsonPropertyName("trusted")]
        public bool Trusted { get; set; }

        [JsonPropertyName("welcomeEmailSent")]
        public bool WelcomeEmailSent { get; set; }

        [JsonPropertyName("facebookURL")]
        public string FacebookURL { get; set; }

        [JsonPropertyName("googlePlusURL")]
        public string GooglePlusURL { get; set; }

        [JsonPropertyName("linkedinURL")]
        public string LinkedinURL { get; set; }

        [JsonPropertyName("twitterHandle")]
        public string TwitterHandle { get; set; }

        [JsonPropertyName("createdAt")]
        public DateTime CreatedAt { get; set; }

        [JsonPropertyName("createdBy_users_id")]
        public int CreatedBy_Users_Id { get; set; }

        [JsonPropertyName("updatedAt")]
        public DateTime UpdatedAt { get; set; }

        [JsonPropertyName("updatedBy_users_id")]
        public int UpdatedBy_Users_Id { get; set; }

        [JsonPropertyName("company")]
        public object Company { get; set; }

        [JsonPropertyName("lastTicketDate")]
        public DateTime? LastTicketDate { get; set; }

        [JsonPropertyName("numTickets")]
        public int NumTickets { get; set; }
    }

    public class RootObject
    {
        [JsonPropertyName("customers")]
        public List<RootObject> Customers { get; set; }

        [JsonPropertyName("totalCustomers")]
        public int TotalCustomers { get; set; }
    }
}

Folder (Pages) | Teamwork.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Vanilla.Models.TeamworkDesk;

namespace Vanilla.Pages
{
    public class TeamworkModel : PageModel
    {

        private readonly IHttpClientFactory _clientFactory;

        public IEnumerable<Customer> Customers { get; private set; }

        public bool GetCustomersError { get; private set; }

        public TeamworkModel(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }


        public async Task OnGet()
        {
            var request = new HttpRequestMessage(HttpMethod.Get,"https://vanillacompany.teamwork.com/desk/v1/customers.json");

            var client = _clientFactory.CreateClient();

            var byteArray = Encoding.ASCII.GetBytes("myUniqueKey:");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                using var responseStream = await response.Content.ReadAsStreamAsync();
                Customers = await JsonSerializer.DeserializeAsync<IEnumerable<Customer>>(responseStream);

            }
            else
            {
                GetCustomersError = true;
                Customers = Array.Empty<Customer>();
            }

        }
    }

}

Folder (Pages) | Teamwork.cshtml

@page
@model Vanilla.Pages.TeamworkModel
@{
    ViewData["Title"] = "Teamwork Customers";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

@if (Model.GetCustomersError)
{
    <p>Unable to get customers from Teamwork. Please try again later.</p>
}
else
{
<ul>
    @foreach (var customer in Model.Customers)
    {
        <li>@customer.FirstName</li>
    }
</ul>

JSON Example:

{
    "customers": [
        {
            "id": 94572,
            "timezoneId": 0,
            "avatarURL": "https://vanillacompany.teamwork.com/desk/images/examples/noPhoto1.png",
            "email": "testytester@vanillacompany.com",
            "contacts": [
                {
                    "id": 44783,
                    "value": "testytester@vanillacompany.com",
                    "type": "email",
                    "isMain": true,
                    "createdAt": "0001-01-01T00:00:00Z"
                }
            ],
            "externalId": "",
            "extraData": "",
            "firstName": "Testy",
            "jobTitle": "Code Tester",
            "language": "en",
            "lastName": "Tester",
            "address": "",
            "mobile": "",
            "notes": "",
            "organization": "Vanilla",
            "phone": "",
            "trusted": false,
            "welcomeEmailSent": false,
            "facebookURL": "",
            "googlePlusURL": "",
            "linkedinURL": "",
            "twitterHandle": "",
            "createdAt": "0001-01-01T00:00:00Z",
            "createdBy_users_id": 166240,
            "updatedAt": "0001-01-01T00:00:00Z",
            "updatedBy_users_id": 166240,
            "company": null,
            "lastTicketDate": null,
            "numTickets": 11
        },
        {
            "id": 85469,
            "timezoneId": 0,
            "avatarURL": "https://vanillacompany.teamwork.com/desk/images/examples/noPhoto2.png",
            "email": "codebreaker@vanillacompany.com",
            "contacts": [
                {
                    "id": 45002,
                    "value": "codebreaker@vanillacompany.com",
                    "type": "email",
                    "isMain": true,
                    "createdAt": "0001-01-01T00:00:00Z"
                }
            ],
            "externalId": "",
            "extraData": "",
            "firstName": "Code",
            "jobTitle": "",
            "language": "en",
            "lastName": "Breaker",
            "address": "",
            "mobile": "",
            "notes": "",
            "organization": "Vanilla",
            "phone": "",
            "trusted": false,
            "welcomeEmailSent": false,
            "facebookURL": "",
            "googlePlusURL": "",
            "linkedinURL": "",
            "twitterHandle": "",
            "createdAt": "0001-01-01T00:00:00Z",
            "createdBy_users_id": 166240,
            "updatedAt": "2016-05-04T20:46:10Z",
            "updatedBy_users_id": 166240,
            "company": null,
            "lastTicketDate": "2017-03-22T19:24:47Z",
            "numTickets": 5
        },
        {
            "id": 69421,
            "timezoneId": 0,
            "avatarURL": "https://vanillacompany.teamwork.com/desk/images/examples/noPhoto3.png",
            "email": "enduser@vanillacompany.com",
            "contacts": [
                {
                    "id": 45032,
                    "value": "enduser@vanillacompany.com",
                    "type": "email",
                    "isMain": true,
                    "createdAt": "2016-02-03T18:57:16Z"
                }
            ],
            "externalId": "",
            "extraData": "",
            "firstName": "End",
            "jobTitle": "",
            "language": "",
            "lastName": "User",
            "address": "",
            "mobile": "",
            "notes": "",
            "organization": "",
            "phone": "999-777-8888",
            "trusted": false,
            "welcomeEmailSent": false,
            "facebookURL": "",
            "googlePlusURL": "",
            "linkedinURL": "",
            "twitterHandle": "",
            "createdAt": "2016-02-03T18:57:16Z",
            "createdBy_users_id": 015874,
            "updatedAt": "2016-04-05T16:49:26Z",
            "updatedBy_users_id": 015874,
            "company": null,
            "lastTicketDate": "2016-04-05T16:48:27Z",
            "numTickets": 23
        },
    ],
    "totalCustomers": 1294
}

Thank you.

dbc
  • 104,963
  • 20
  • 228
  • 340
exaas
  • 43
  • 1
  • 4

1 Answers1

0

Your Json is fine, you've just mixed up some of the targets for deserialization. Using your existing code I would make these changes.

In the class RootObject change the Customers property to be of type List<Customer>:

public List<Customer> Customers { get; set; }

In Teamwork.cshtml.cs change the Customers property to be of type RootObject:

public RootObject Customers { get; private set; }

Then change the deserialize line to read:

Customers = await JsonSerializer.DeserializeAsync<RootObject>(responseStream);

Finally, as a personal preference I would change RootObject to be named something like CustomerList.

Crater
  • 349
  • 4
  • 5
  • Thank you! I had tried a few combinations of those changes, but not those all together. I took your recommendation and updated the RootObject as well since it did not provide a meaningful name. – exaas Dec 05 '19 at 22:01