应用程序数据的 WebClient 下载未将结果集返回到 reader

WebClient download of application data not returning result set into reader

我在使用这段代码时遇到了一个主要问题 我正在尝试简单地从基于 xml 的 craftycllick 服务器下载地址列表 我正在使用 webclient 进行下载但是当我去的时候它失败了到浏览器的数据是

 public XmlTextReader readXML(string postcode, string response, string accessCode)
 {
        //Create URL
        string url = $"http://pcls1.craftyclicks.co.uk/xml/rapidaddress?postcode={postcode}&response={response}&key={accessCode}";

        try
        {
            //Create WebRequest
            WebRequest request = WebRequest.Create(url);
            using (Stream responseStream = request.GetResponse().GetResponseStream())
            {
                if (responseStream != null)
                {
                    using (TextReader textReader = new StreamReader(responseStream))
                    {
                        XmlTextReader reader = new XmlTextReader(textReader);
                        Debug.Assert(reader != null, "Reader is NULL");
                        return reader;
                    }
                }
                throw new Exception("ResponseStream is NULL");
            }
        }
        catch (WebException ex)
        {
            return null;
        }
}
返回的

Xml 是

  <CraftyResponse><address_data_formatted><delivery_point><organisation_name>THE BAKERY</organisation_name><department_name/><line_1>1 HIGH STREET</line_1><line_2>CRAFTY VALLEY</line_2><udprn>12345678</udprn></delivery_point><delivery_point><organisation_name>FILMS R US</organisation_name><department_name/><line_1>3 HIGH STREET</line_1><line_2>CRAFTY VALLEY</line_2><udprn>12345679</udprn></delivery_point><delivery_point><organisation_name>FAMILY BUTCHER</organisation_name><department_name/><line_1>7 HIGH STREET</line_1><line_2>CRAFTY VALLEY</line_2><udprn>12345680</udprn></delivery_point><delivery_point><organisation_name/><department_name/><line_1>BIG HOUSE, HIGH STREET</line_1><line_2>CRAFTY VALLEY</line_2><udprn>12345681</udprn></delivery_point><delivery_point><organisation_name/><department_name/><line_1>LITTLE COTTAGE</line_1><line_2>17 HIGH STREET, CRAFTY VALLEY</line_2><udprn>12345682</udprn></delivery_point><delivery_point_count>5</delivery_point_count><town>BIG CITY</town><postal_county>POSTAL COUNTY</postal_county><traditional_county>TRADITIONAL COUNTY</traditional_county><postcode>AA1 1AA</postcode></address_data_formatted></CraftyResponse>

以及我用来解析的例程。

public DataTable returnAddressList(string postcode, string accessCode)
    {
        try
        {
            DataTable dtReturn = new DataTable();
            dtReturn.Columns.Add("PropertyItem", Type.GetType("System.String"));
            dtReturn.Columns.Add("PropertyValue", Type.GetType("System.String"));

            postcode = postcode.Replace(" ", "");
            XmlTextReader reader = readXML(postcode, "data_formatted", accessCode);

            string option1 = "";
            string option2 = "";

            while (reader.Read())
            {

                if (reader.Name.Equals("line_1"))
                {
                    option1 = reader.ReadString();
                }
                if (reader.Name.Equals("udprn"))
                {
                    option2 = reader.ReadString();
                }
                if (option1 != "" && option2 != "")
                {
                    dtReturn.Rows.Add(new object[] { option1, option2 });
                    option1 = "";
                    option2 = "";
                }
            }

            return dtReturn;
        }

        catch (Exception ex)
        {
            return null;
        }
    }

我对上述函数的调用代码是

  fhsBl.Helpers.CraftyPostCodeLookup _postCodeLookup = new fhsBl.Helpers.CraftyPostCodeLookup();

        DataTable dt = new DataTable();

       dt = _postCodeLookup.returnAddressList("AA11AA", "API KEY DONT BE NOSY");

编辑 1 好的,建议我更改我的代码以使用 using 语句并阅读其中的内容,但我收到另一个错误并且仍然没有生成数据。

 public DataTable readXML(string postcode, string response, string accessCode)
    {
        //Create URL
        string url = $"http://pcls1.craftyclicks.co.uk/xml/rapidaddress?postcode={postcode}&response={response}&key={accessCode}";

        try
        {
            DataTable dtReturn = new DataTable();
            dtReturn.Columns.Add("PropertyItem", Type.GetType("System.String"));
            dtReturn.Columns.Add("PropertyValue", Type.GetType("System.String"));

            //Create WebRequest
            WebRequest request = WebRequest.Create(url);
            using (Stream responseStream = request.GetResponse().GetResponseStream())
            {
                if (responseStream != null)
                {
                    using (TextReader textReader = new StreamReader(responseStream))
                    {
                        XmlTextReader reader = new XmlTextReader(textReader);
                        postcode = postcode.Replace(" ", "");

                        string option1 = "";
                        string option2 = "";

                        while (reader.Read())
                        {

                            if (reader.Name.Equals("line_1"))
                            {
                                option1 = reader.ReadString();
                            }
                            if (reader.Name.Equals("udprn"))
                            {
                                option2 = reader.ReadString();
                            }
                            if (option1 != "" && option2 != "")
                            {
                                dtReturn.Rows.Add(new object[] { option1, option2 });
                                option1 = "";
                                option2 = "";
                            }
                        }
                        return dtReturn;
                    }
                }
                throw new Exception("ResponseStream is NULL");
            }
        }
        catch (WebException ex)
        {
            return null;
        }
    }

调试的屏幕截图

好的。当您想要 return 流时,您不能从 using statment return,因为当您从 using 退出时,您调用 Dispose 方法并关闭流。

首先你必须改变readXML方法。

public DataTable readXML(string postcode, string response, string accessCode)
 {
        //Create URL
        string url = $"http://pcls1.craftyclicks.co.uk/xml/rapidaddress?postcode={postcode}&response={response}&key={accessCode}";

        DataTable dataTableResult  = null;

        try
            //Create WebRequest
            WebRequest request = WebRequest.Create(url);
            using (Stream responseStream = request.GetResponse().GetResponseStream())
            {
                if (responseStream != null)
                {
                    using (TextReader textReader = new StreamReader(responseStream))
                    {
                        XmlTextReader reader = new XmlTextReader(textReader);
                        Debug.Assert(reader != null, "Reader is NULL");

                        dataTableResult = returnAddressList(postcode, response, reader)
                    }
                }
                throw new Exception("ResponseStream is NULL");
            }

           return dataTableResult;
        }
        catch (WebException ex)
        {
            return null;
        }

接下来您必须更改 returnAddressList 方法的定义以使用来自参数的流,如下所示:

   public DataTable returnAddressList(string postcode, string accessCode, XmlTextReader reader)

并删除了您调用 readXML 方法的行

  XmlTextReader reader = readXML(postcode, "data_formatted", accessCode); - delete this line

不是很好的重构,但是你可以看到要做什么以及问题出在哪里。

随着评论中的讨论...

using (TextReader textReader = new StreamReader(responseStream))
                {
                    XmlTextReader reader = new XmlTextReader(textReader);
                    Debug.Assert(reader != null, "Reader is NULL");
                    return reader;
                }

您创建了一个 TextReader 对象,稍后您将在 XmlTextReader 的构造函数中使用该对象 reader ... 在您 return XmlTextReader 之后,当您退出使用块时,您将处理并关闭 textReader ,因此出现无法从关闭的 textReader 中读取的错误。问题出在我的架构上。

您应该尝试将 while 循环逻辑从您拥有的 Parse 方法中提取到 using 块中,例如....

using(TextReader textReader = new StreamReader(responseStream))
        {
            XmlTextReader reader = new XmlTextReader(textReader);

            while(reader.Read())
            {
                if(reader.Name.Equals("line_1"))
                {
                    option1 = reader.ReadString();
                }
                if(reader.Name.Equals("udprn"))
                {
                    option2 = reader.ReadString();
                }
                if(option1 != "" && option2 != "")
                {
                    dtReturn.Rows.Add(new object[] { option1, option2 });
                    option1 = "";
                    option2 = "";
                }
            }
        }