解决 从API响应中读取数据

已加入
2020年3月20日
留言内容
65
编程经验
10+
大家好

我目前正在使用REST API,并且在读取响应数据时需要一些指导。我在读取此类数据方面的经验非常少,我正在尝试找到最佳方法。

以下是获取API数据的代码。

C#:
 public string ModitarWebRequestCall()
        {
            string apiUrl = "//api.moditar.com/Document/GetContent";
            string username = "JohnDoe";
            string password = "Password123";
            string collection = "ea85fbf3-5858-4348-bcab-08a8f39ad30c";
            string markasread = "False";

            var 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);

            string content = string.Empty;
            try
            {
                using (var response = (HttpWebResponse)request.GetResponse())
                {
                    using (var stream = response.GetResponseStream())
                    {
                        using (var sr = new StreamReader(stream))
                        {
                            content = sr.ReadToEnd();
                            sr.Close();
                            Console.WriteLine("Data received from Moditar");
                        }
                    }
                }
                return content;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
        }

我正在使用下面的代码来调用上述方法,这是我需要处理数据的地方。

C#:
        public void ProcessDatafromModitarApi()
        {
            var getData = new ModitarApiConnection();
            getData.ModitarWebRequestCall();
        }

读取此数据的最佳方法是什么?有json,xml读取器选项,将其保留为文本等选项,因此有很多选择。任何对此的指导将不胜感激。
 
已加入
2020年3月20日
留言内容
65
编程经验
10+
否。这是将读取XML数据的类。通常,类类型名称与XML元素名称匹配,但是可以重写。您应该花一些时间阅读有关XML序列化和反序列化的信息,而不是仅仅在屏幕上扔代码以查看问题所在。


啊,我现在知道OrderedItem的来源,我同意我需要在序列化等方面花费更多的时间,但与此同时我有点时间紧缩。我还需要更多有关XML的经验,这是我开发生涯的一部分,多年来我一直完全忽略这一部分。香港专业教育学院创建了OrderedItem类,并测试您的建议,但我得到一个"不能隐式地将类型隐式转换为字符串" in this below line.

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

有任何想法吗 ?
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,528
地点
弗吉尼亚州切萨皮克
编程经验
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.
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,528
地点
弗吉尼亚州切萨皮克
编程经验
10+
已加入
2020年3月20日
留言内容
65
编程经验
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.

谢谢跳伞运动员,我要摆脱这一点,让我感到沮丧,犯下愚蠢的错误,错过明显的事情。实际上,我有一个ProcessXML类,该类调用ModitarWebrequestCall方法,我应该在该类中进行反序列化和xml读取,我的最初想法是将数据返回到字符串中并从那里进行工作,但完全失去了重点。我试图坚持“单一责任原则”,让我的课程只关注一件事。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,528
地点
弗吉尼亚州切萨皮克
编程经验
10+
在这种情况下,您在第一篇文章中的原始代码大部分是正确的。您所需要做的就是使用流阅读器读到末尾并返回字符串。阅读完最后内容后,无需调用Deserialize()。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
在这种情况下,您在第一篇文章中的原始代码大部分是正确的。您所需要做的就是使用流阅读器读到末尾并返回字符串。阅读完最后内容后,无需调用Deserialize()。
可能更正吗?因为Deserializer方法需要xmlreader。 (要点,因为代码p /#1中的源正在接收XML,所以将其切换为XML阅读器)当我有空时,我将为您试一下Alex。自由职业者atm下雪了
 
已加入
2020年3月20日
留言内容
65
编程经验
10+
在这种情况下,您在第一篇文章中的原始代码大部分是正确的。您所需要做的就是使用流阅读器读到末尾并返回字符串。阅读完最后内容后,无需调用Deserialize()。
谢谢跳伞

因此,按照我的原始计划,一旦我获得了数据串,我就需要反序列化以便读取XML。我的想法正确吗?
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,528
地点
弗吉尼亚州切萨皮克
编程经验
10+
参见文章#24 ...他只是想从REST Web服务返回字符串。他实际上并不想在同一个班级中反序列化。他还有另一个课程要进行反序列化。

我的一部分感到 HttpClient.GetStringAsync() 也许仅是一种简单的方法来获取字符串,但仅适用于客户端使用的非标准身份验证方案。
 
已加入
2020年3月20日
留言内容
65
编程经验
10+
可能更正吗?因为Deserializer方法需要xmlreader。 (要点,因为代码p /#1中的源正在接收XML,所以将其切换为XML阅读器)当我有空时,我将为您试一下Alex。自由职业者atm下雪了
毫无疑问,Sheeping完全不用担心,我非常感谢你们抽出宝贵的时间来帮助我学习。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,528
地点
弗吉尼亚州切萨皮克
编程经验
10+
Thanks Skydiver

因此,按照我的原始计划,一旦我获得了数据串,我就需要反序列化以便读取XML。我的想法正确吗?
是的,您有一个字符串,然后将该字符串传递到解串器中。

从流到字符串以及从字符串到对象似乎效率不高,但这实际上取决于单元测试的设置方式。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
毫无疑问,Sheeping完全不用担心,我非常感谢你们抽出宝贵的时间来帮助我学习。
别傻了,这就是我们在这里的全部目的。我们的工作是提供解决方案。抱歉,我没有在您身上提供源代码来帮助您。今天我的双手被绑住了,我只有时间在自动取款机上提出建议了。

跳伞运动员将您带入正确的轨道,并记下第30条帖子,其中他指出了代码中的一行,我也称其为多余的行。

如果要使用任何阅读器,请直接将阅读器传递给进行反序列化,而不是从流转向字符串。就像我提到的那样
 
已加入
2020年3月20日
留言内容
65
编程经验
10+
谢谢大家,我回来了,希望我头脑清醒。仅根据最后两篇文章进行说明,对我而言,最好反序列化流,然后将该对象传递回我的调用方法,而不是将流传递给字符串,然后再传递给对象。
 
已加入
2020年3月20日
留言内容
65
编程经验
10+
看来我终于取得了一些进展,设法对流数据进行反序列化,下一步是尝试读取XML。

C#:
 public class ModitarApiConnection
    {
        public class Document
        {
            
        }
        public Object ModitarWebRequestCall()
        {
            string apiUrl = "//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;
            }
        }
    }

请让我知道你们是否可以发现任何错误或在上述代码中我可以做得更好的事情,以尽我所能来学习。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,528
地点
弗吉尼亚州切萨皮克
编程经验
10+
Delete line 30. You are not using the StreamReader anyway.

您确实应该将9-12行(或9-13行)上的那些魔术字符串放入app.config或web.config中。在代码中嵌入密码和其他机密通常不是一个好主意。对于玩具应用程序或原型,但是您在此线程和另一个线程中指出这是要出租的生产工作,因此您可能希望使代码更适合生产。

正在做 宠物小精灵异常处理 除非这是一个玩具应用程序,否则在第39行上通常不是一个好主意。您先前在此线程和另一个线程中指示这是要出租的生产工作,因此您可能希望使代码更适合生产。

您是否考虑过如果密码或用户名不在ASCII范围内会发生什么情况?

您是否考虑过使用 HttpClient 或者 网络客户端 classes instead?

编码风格的东西:

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.

注意第25-38行如何越来越深地嵌入并且看起来像箭头。有人称这为"arrow pattern"并认为这是一种反模式,因为深度嵌套使读取代码变得更加困难。在C#8.0之前,通常的编码方式是将其重写为:
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;
    }
}
但是,如果您具有C#8.0,则可以将其进一步重写为:
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;
}
 
已加入
2020年3月20日
留言内容
65
编程经验
10+
嗨跳伞

多谢您的回覆和宝贵建议,"magic strings"将从将在主应用程序中设置的数据库中的字段填充,我只是将它们硬编码以用于测试目的,并且与错误陷阱和异常相同,一旦弄清楚了XML,我将使其变得更加健壮。我很高兴您提到var关键字,我使用的是Visual Studio 2019,而最新的C#和VS 2019始终建议我在使用var时都使用隐式约定,所以我认为这是新的规范(很高兴它不是t)哈哈,我更喜欢var。我现在正在努力的一件事是读取返回的对象,我不确定100%如何做到这一点。这是我的调用方方法(仍保持不变),我不确定要反复遍历以读取数据。

C#:
    class ProcessXML
    {
        public void ProcessDatafromModitarApi()
        {
            var getData = new ModitarApiConnection();
            getData.ModitarWebRequestCall();
        }
    }

再次感谢Skydiver,我现在将对代码进行那些改进。

Mod编辑,无需引用您上方的人。大量引用已删除。
 
由主持人最后编辑:
最佳 底部