Avatar of N M
N M
Flag for Luxembourg asked on

C# - JSON Serialization using model

I have a C# small console app that I need to run, it consumes an HTTP restful API. My problem is that using JSON I get a "Cannot implement type blahblah with a collection initializer because it does not implement 'System.Collections.IEnumerable' " and I'm lost. Coud you help me please? Posting the relevant part of the code..

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace TESTMEname
{

    public class headers
    {
        public string Request_ID { get; set; } = "XX123456789";
        public string Correlation_ID { get; set; } = "12345678910";
        public string Token { get; set; } = "abcdefghijklmnopqrstuvwxyzetc";
        public string Content_Type { get; set; } = "application/x-www-form-urlencoded";
    }

    public class access
    {
        public string allPs { get; set; } = "allAccounts";
        public string availableAccounts { get; set; } = "allAccounts";
    }

    public class Body
    {
        public access access { get; set; }
        public bool combinedServiceIndicator { get; set; } = false;
        public int frequencyPerDay { get; set; } = 4;
        public bool recurringIndicator { get; set; } = false;
        public string validUntil { get; set; } = "2020-12-31";
    }

    [System.Serializable]
    public class Consent    //RootObject
    {
        public headers headers { get; set; }
        public Body body { get; set; }
    }

Open in new window


and my class is

class Program
    {
        static HttpClient client = new HttpClient();

        static void ShowConsent(Consent cust_consent)
        {
            Console.WriteLine(cust_consent.ToString());
        }

        static async Task<Uri> CreateConsentAsync(Consent cust_consent)
        {
            HttpResponseMessage response = await client.PostAsJsonAsync("http://myniceurl:8001/some/good/url/", cust_consent);

            ShowConsent(cust_consent);

            response.EnsureSuccessStatusCode();

            // return URI of the created resource.
            return response.Headers.Location;
        }

        static async Task<Consent> GetConsentAsync(string path)
        {
            Consent cust_consent = null;

            HttpResponseMessage response = await client.GetAsync(path);

            if (response.IsSuccessStatusCode)
            {
                cust_consent = await response.Content.ReadAsAsync<Consent>();
            }

            return cust_consent;
        }

Open in new window


When I try to populate I simple can't

        static void Main()
        {

            RunAsync().GetAwaiter().GetResult();
        }



        static async Task RunAsync()
        {
            // Update port # and url in the following line.
            client.BaseAddress = new Uri("http://myurl:8001/etc..../");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            try
            {
                // Create a new cust_consent  <------- fails!!!!!!!
                Consent cust_consent = new Consent
                {
                    cust_consent.headers.Request_ID  = "something",

                    cust_consent.body.access.allPs = "new_value",
                    cust_consent.body.access.availableAccounts = "new_value",
                    cust_consent.body.combinedServiceIndicator = false,
                    cust_consent.body.frequencyPerDay = 4,
                    cust_consent.body.recurringIndicator = false,
                    cust_consent.body.validUntil = "some_date_YYYYMMDD"
			...etc...
                };

                string json = JsonConvert.SerializeObject(cust_consent);
                Console.WriteLine(json);
                Console.WriteLine("----------------------------------------------------------");
                var url = await CreateConsentAsync(cust_consent);

                Console.WriteLine($"Created at {url}");

                ShowConsent(cust_consent);

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadLine();

        }
    }
}

Open in new window

C#JSON

Avatar of undefined
Last Comment
N M

8/22/2022 - Mon
N M

ASKER
This is the JSON I am trying to POST to the url (hope is ok):

{
"headers":
	{
	"X-Request-ID":"something",
	"LH-Correlation-ID":"something",
	"LH-PSU-Token":"anicevaluehere",
	"Content-Type":"application/x-www-form-urlencoded"
	},
"body":
	{
	  "access": {
		"allPsd2": "allAccounts",
		"availableAccounts": "allAccounts"
				},
	  "combinedServiceIndicator": false,
	  "frequencyPerDay": 4,
	  "recurringIndicator": false,
	  "validUntil": "2022-12-31"
	}
}

Open in new window


Hope it helps..
leakim971

"X-Request-ID" different to "Request_ID "
same for other fields, use :


    public class headers
    {
        [JsonProperty("X-Request-ID")]
        public string Request_ID { get; set; } = "XX123456789";
        [JsonProperty("LH-Correlation-ID")]
        public string Correlation_ID { get; set; } = "12345678910";
        [JsonProperty("LH-PSU-Token")]
        ...

Open in new window

N M

ASKER
Thank you, did that already (adding JSON prooerties)

however, when I try to populate, I get the error..

Any suggestions?

Thank you very much
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
leakim971

Any suggestions?

try simple object
and add new "property" one by one until it fail

so first try to post a simple like this one :
{"headers":{"a":"something"}}

of course update the class so it match everytime you add a new property
N M

ASKER
Thank you
I tried, it partially works up to the point that I have the "access" with two nested properties.
Then, the JSON serialization fails..

With the above code, seems the only problem populating the properties is this error, hence I am trying to see what it means (I tried "by the book" example of Microsoft but did not work, and interestingly enough, I end up with same error..
leakim971

Body class the B is uppercase, is it OK ?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
N M

ASKER
Yes, it works as well in lowercase.
leakim971

here on the documentation : https://docs.microsoft.com/fr-fr/dotnet/standard/serialization/system-text-json-how-to

check the TemperatureRanges:

public Dictionary<string, HighLowTemps> TemperatureRanges { get; set; }

using this tools : https://app.quicktype.io/#l=cs&r=json2csharp

I get :

// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using QuickType;
//
//    var welcome = Welcome.FromJson(jsonString);

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Welcome
    {
        [JsonProperty("headers")]
        public Headers Headers { get; set; }

        [JsonProperty("body")]
        public Body Body { get; set; }
    }

    public partial class Body
    {
        [JsonProperty("access")]
        public Access Access { get; set; }

        [JsonProperty("combinedServiceIndicator")]
        public bool CombinedServiceIndicator { get; set; }

        [JsonProperty("frequencyPerDay")]
        public long FrequencyPerDay { get; set; }

        [JsonProperty("recurringIndicator")]
        public bool RecurringIndicator { get; set; }

        [JsonProperty("validUntil")]
        public DateTimeOffset ValidUntil { get; set; }
    }

    public partial class Access
    {
        [JsonProperty("allPsd2")]
        public string AllPsd2 { get; set; }

        [JsonProperty("availableAccounts")]
        public string AvailableAccounts { get; set; }
    }

    public partial class Headers
    {
        [JsonProperty("X-Request-ID")]
        public string XRequestId { get; set; }

        [JsonProperty("LH-Correlation-ID")]
        public string LhCorrelationId { get; set; }

        [JsonProperty("LH-PSU-Token")]
        public string LhPsuToken { get; set; }

        [JsonProperty("Content-Type")]
        public string ContentType { get; set; }
    }

    public partial class Welcome
    {
        public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}

Open in new window

N M

ASKER
(Note: I understand the effort on the date property, thing is, apart from integers and boolean values, all rest are strings, so, no need for extra effort on converting dates etc, is all same for me)
Thank you also for the suggestion on the quicktype. Is very interesting. However, my problem seems to be exactly at the point where I assign the values... I am trying now and will post a sample *if it compiles...
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
leakim971

can't compile for the moment, don't have the right machine
I will and try to provide a working sample until you do it before
ASKER CERTIFIED SOLUTION
kaufmed

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
N M

ASKER
Thank you, it worked immediately.
N M

ASKER
Thanks 'leakim971' for his advice, thank you 'kaufmed' for posting compiling code and explaining logic.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.