Resolved Read data from API response

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
No. It's a class where the XML data will be read into. Typically the class type name matches the XML element name but this can be overridden. You should take time to read about XML serialization and deserialization instead of just throwing code at the screen to see what sticks.

Ah i see now where the OrderedItem comes from, I agree I need to spend more time on serialization etc but i'm on a bit of a time crunch with this one. I also need more experience with XML , this is one section of my development career that i have ignored completely over the years. Ive created the OrderedItem class and testing your suggestion out but i get a "cannot implicitly covert type to string" in this below line.

C#:
return (OrderedItem)serializer.Deserialize(stream);
Any ideas ?
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,788
Location
Chesapeake, VA
Programming Experience
10+
Yes, because a class OrderedItem cannot be convert to a string. You declared your ModitarWebRequestCall() to return a string in your line #1:
C#:
public string ModitarWebRequestCall()
Perhaps your should return a OrderedItem instead of a string.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,788
Location
Chesapeake, VA
Programming Experience
10+
I agree I need to spend more time on serialization etc but i'm on a bit of a time crunch with this one.
Tell your manager you need time to learn.
 

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Yes, because a class OrderedItem cannot be convert to a string. You declared your ModitarWebRequestCall() to return a string in your line #1:
C#:
public string ModitarWebRequestCall()
Perhaps your should return a OrderedItem instead of a string.
Thanks Skydiver, i'm going to step away from this for a bit I'm getting frustrated and making stupid mistakes and missing obvious things. I actually have a ProcessXML class that calls the ModitarWebrequestCall method, I should be doing me deserialization and xml reading in that class, my initial idea was to get the data back in a string and do the work from there, but completely lost focus. I'm trying to stick to the Single responsibility Principle and have my classes focus on just one thing.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,788
Location
Chesapeake, VA
Programming Experience
10+
In that case, your original code in post #1 was mostly correct. All you needed was to use the stream reader to read to the end and return the string. There was no need to call Deserialize() after reading to the end.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,518
Location
UK
Programming Experience
10+
In that case, your original code in post #1 was mostly correct. All you needed was to use the stream reader to read to the end and return the string. There was no need to call Deserialize() after reading to the end.
Probable correction? Because the Deserializer method wants a xmlreader. (Point, switch it for an XML reader since the source in code p/#1 is receiving XML) As Soon as I am free, I will try this out for you Alex. Just very snowed under with a freelance job atm
 

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
In that case, your original code in post #1 was mostly correct. All you needed was to use the stream reader to read to the end and return the string. There was no need to call Deserialize() after reading to the end.
Thanks Skydiver

So with my original plan, once i got the string of data back, i would then need to deserialise that so that i can read the XML. Is my thinking correct with that ?
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,788
Location
Chesapeake, VA
Programming Experience
10+
See post #24... He just wants to return the string from the REST web service. He didn't actually want to deserialize within the same class. He has another class to do the deserialization.

Part of me feels that the HttpClient.GetStringAsync() maybe an easier way to get just the string, but only for that non-standard authentication scheme that client uses.
 

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Probable correction? Because the Deserializer method wants a xmlreader. (Point, switch it for an XML reader since the source in code p/#1 is receiving XML) As Soon as I am free, I will try this out for you Alex. Just very snowed under with a freelance job atm
No worries at all Sheepings, I really appreciate you guys taking the time to help me with this and learn.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,788
Location
Chesapeake, VA
Programming Experience
10+
Thanks Skydiver

So with my original plan, once i got the string of data back, i would then need to deserialise that so that i can read the XML. Is my thinking correct with that ?
Yes, one you have a string, then you would pass that string into the deserializer.

Seems a little inefficient to go from stream to string and string to object, but it really depends on how your unit tests are setup.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,518
Location
UK
Programming Experience
10+

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,518
Location
UK
Programming Experience
10+
No worries at all Sheepings, I really appreciate you guys taking the time to help me with this and learn.
Don't be silly, that's what we are all here for. Our job is to provide solutions. Sorry I'm not throwing source code at you to help you with this. My hands are tied today, and I've only time to throw advice out there atm.

Skydiver is putting you on the right track, and also take note of post 30 where he points out one of the lines in your code which I also called redundant.

If you are going to use any readers, pass the reader in directly for deserializing, instead of going from stream to string. Etc as I mentioned one page back
 

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Thanks guys, I'm back and hopefully with a clearer head. Just to clarify based on the last two posts, it would be better for me to deserialise the stream and then pass that object back to my calling method, instead of stream to string and then too object.
 

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Looks like i'm finally making some progress, managed to deserialze the stream data, next step is to try and read the XML.

C#:
 public class ModitarApiConnection
    {
        public class Document
        {
            
        }
        public Object ModitarWebRequestCall()
        {
            string apiUrl = "https://api.moditar.com/Document/GetContent";
            string username = "testing123";
            string password = "password1213";
            string collection = "ea85fbf3-5858-4348-bcab-08a8f39ad30c";
            string markasread = "False";

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl);
            request.Method = "GET";
            request.Accept = "application/xml";

            request.Headers.Add("username", username);
            request.Headers.Add("password", password);
            request.Headers.Add("collection", collection);
            request.Headers.Add("Markasread", markasread);

            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader sr = new StreamReader(stream))
                        {
                            var mySerializer = new XmlSerializer(typeof(Document));
                            var myXmlObject = (Document)mySerializer.Deserialize(stream);
                            return myXmlObject;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
        }
    }
Please let me know if you guys can spot anything wrong or something i can do better in the above code, trying to learn as much as i can as i go.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,788
Location
Chesapeake, VA
Programming Experience
10+
Delete line 30. You are not using the StreamReader anyway.

You really should put those magic strings on lines 9-12 (or 9-13 ?) into your app.config or web.config. Embedding passwords and other secrets in code is typically a bad idea. For a toy application or prototoype, but you indicated in this thread and another thread that this is production work for hire so you may want to make your code more production ready.

Doing Pokemon exception handling on line 39 is usually a bad idea unless this is a toy application. You previously indicated in this thread and another thread that this is production work for hire so you may want to make your code more production ready.

Have you considered what happens if the password or username is not in the ASCII range?

Have you considered using the HttpClient or WebClient classes instead?

Coding style things:

The new coding style recommendations for C# is to prefer using var instead of explicitly putting in the type if the type can be easily implied from the assignment.

Notice how lines 25-38 gets more and more deeply embedded and looks like an arrow. Some people call this an "arrow pattern" and consider it an anti-pattern because the deep nesting makes it harder to read the code. Prior to C# 8.0, the usual coding style would be to re-write it as:
C#:
try
{
    using (var response = (HttpWebResponse)request.GetResponse())
    using (var stream = response.GetResponseStream())
    {
        var mySerializer = new XmlSerializer(typeof(Document));
        var myXmlObject = (Document)mySerializer.Deserialize(stream);
        return myXmlObject;
    }
}
But if you have C# 8.0, this could be further re-written as:
C#:
try
{
    using var response = (HttpWebResponse)request.GetResponse();
    using var stream = response.GetResponseStream();
    var mySerializer = new XmlSerializer(typeof(Document));
    var myXmlObject = (Document)mySerializer.Deserialize(stream);
    return myXmlObject;
}
 

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Hi Skydiver

Thank you for your reply and the great suggestions, the "magic strings" will be populated from fields in a database that will be setup in the main application, I just hard coded them in for testing purposes and the same with the error trapping and exceptions, i'll make those more robust once I have the XML figured out. I'm glad you mentioned the var keyword, I'm using Visual Studio 2019 and the latest C# and VS 2019 keeps suggesting that i use the implicit convention whenever i use var, so i thought that was the new norm (glad it isn't) lol, I way prefer var. The one thing I'm struggling with now is reading the returned object, i'm not 100% sure how to do that. Here is my caller method (still unchanged), i'm not sure what to iterate through to read the data.

C#:
    class ProcessXML
    {
        public void ProcessDatafromModitarApi()
        {
            var getData = new ModitarApiConnection();
            getData.ModitarWebRequestCall();
        }
    }
Thanks again Skydiver, I'm going to make those improvements to my code now.

Mod edit, no need to quote the person directly above you. Massive quote removed.
 
Last edited by a moderator:

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Thank you so much for your help guys, I've managed to make some progress. I'm going to mark this thread resolved and will start a new one if I face any other problems.
 
Top Bottom