为什么在调用Web服务时可选的xml参数不起作用?

时间:2013-12-22 11:09:19

标签: c# asp.net web-services soap wsdl

大家好我是编程和尝试学习网络服务的新手,请帮我解决这个问题!

我正在尝试使用httpWebRequest将soap xml发布到http://www.webservicex.net/globalweather.asmx,使用以下xml和visual studio。

<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body>
<GetWeather xmlns='http://www.webserviceX.NET'>
<CountryName>Canada</CountryName>
<CityName></CityName>
</GetWeather>
</soap:Body>
</soap:Envelope> 

这里的问题是如果我将CityName留空,则返回Data Not Found,但是当我使用soap ui发送相同的xml时,可以返回正确的天气信息,因为WSDL http://www.webservicex.net/globalweather.asmx?WSDL表明CityName是可选的。

如果有人能告诉我怎么能让这个工作,我将不胜感激。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

namespace Assignment1.Tests
{
    public partial class task2async : System.Web.UI.Page
    {  
        protected void Page_Load(object sender, EventArgs e)
        {
            //build url
            UriBuilder _url = new UriBuilder();

            _url.Scheme = "http";
            _url.Host = "www.webservicex.net";
            _url.Path = "globalweather.asmx";
            string _action = "http://www.webserviceX.NET/GetWeather";
            //creating a request
            HttpWebRequest req=(HttpWebRequest)CreateRequest(_url.ToString(), _action);
            //being async request stream 
            try
            {
                req.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), req);
            }
            catch (Exception ex)
            {

                Debug.WriteLine("Something wrong at asyncallback");
            }
        }
        public static HttpWebRequest CreateRequest (string url, string action)
        {
            try {
                //creating httpwebrequest object
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Headers.Add("SOAPAction", action);
                request.ContentType = "text/xml;charset=\"UTF-8\"";
                request.KeepAlive = true;
                request.Method = "POST";
                return request;
            }
            catch(Exception e)
            {
                return null;
            }
        }

        public static XmlDocument createSoapEnvelop()
        {
            try
            {
                XmlDocument soapEvelope = new XmlDocument();
                soapEvelope.LoadXml("<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><GetWeather xmlns='http://www.webserviceX.NET'><CountryName>Canada</CountryName><CityName></CityName></GetWeather></soap:Body></soap:Envelope>");
                return soapEvelope;

            }
            catch (Exception e)
            {
                return null;
            }

        }
        // using makes sure unused resources are released as soon


        void GetRequestStreamCallback(IAsyncResult callbackResult)
        {
            HttpWebRequest webRequest = (HttpWebRequest)callbackResult.AsyncState;
            XmlDocument soapevelop = createSoapEnvelop();
            Stream postStream = webRequest.EndGetRequestStream(callbackResult);
            soapevelop.Save(postStream);
            webRequest.BeginGetResponse(new AsyncCallback(GetResponseStreamCallback), webRequest);

        }

        void GetResponseStreamCallback(IAsyncResult callbackResult)
        {
            HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
            using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
            {
                string result = httpWebStreamReader.ReadToEnd();
                Debug.WriteLine(result);
            }
        }     
    }
}

2 个答案:

答案 0 :(得分:1)

我可以告诉你哪里出了问题,但我无法弄清楚你需要在哪里调整你的代码。 请打开你的wsdl并在wsdl的末尾看到服务标签。你会找到4个端口。

 <wsdl:service name="GlobalWeather">
<wsdl:port name="GlobalWeatherSoap" binding="tns:GlobalWeatherSoap">
  <soap:address location="http://www.webservicex.net/globalweather.asmx" />
</wsdl:port>
<wsdl:port name="GlobalWeatherSoap12" binding="tns:GlobalWeatherSoap12">
  <soap12:address location="http://www.webservicex.net/globalweather.asmx" />
</wsdl:port>
<wsdl:port name="GlobalWeatherHttpGet" binding="tns:GlobalWeatherHttpGet">
  <http:address location="http://www.webservicex.net/globalweather.asmx" />
</wsdl:port>
<wsdl:port name="GlobalWeatherHttpPost" binding="tns:GlobalWeatherHttpPost">
  <http:address location="http://www.webservicex.net/globalweather.asmx" />
</wsdl:port>

您正在尝试按照GlobalWeatherSoap提供输入时执行GlobalWeatherHttpPost。 那就是问题所在.. 如果你想使用httppost方法,那么这将是你的操作。

<wsdl:operation name="GetWeather"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get weather report for all major cities around the world.</wsdl:documentation> <wsdl:input message="tns:GetWeatherHttpPostIn" /> <wsdl:output message="tns:GetWeatherHttpPostOut" /> </wsdl:operation>

您需要按照以下绑定实施

<wsdl:binding name="GlobalWeatherHttpPost" type="tns:GlobalWeatherHttpPost">
<http:binding verb="POST" />
<wsdl:operation name="GetWeather">
  <http:operation location="/GetWeather" />
  <wsdl:input>
    <mime:content type="application/x-www-form-urlencoded" />
  </wsdl:input>
  <wsdl:output>
    <mime:mimeXml part="Body" />
  </wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetCitiesByCountry">
  <http:operation location="/GetCitiesByCountry" />
  <wsdl:input>
    <mime:content type="application/x-www-form-urlencoded" />
  </wsdl:input>
  <wsdl:output>
    <mime:mimeXml part="Body" />
  </wsdl:output>
</wsdl:operation>

请相应地修改您的代码。请在wsdl中输入和输出消息格式以进行此操作。

编辑代码更正: “但是当我使用soap ui发送相同的xml时,可以返回正确的天气信息,因为WSDL http://www.webservicex.net/globalweather.asmx?WSDL声明CityName是可选的。”

在soapui中,它将仅为soap操作创建rquest,而不是httpget和httppost。

实施httppost: 1.删​​除此

request.Headers.Add("SOAPAction", action);

2.删除代码中的soap包围创作。

3.在代码中调用post请求时,传递CityName = string&amp; CountryName = string   而不是肥皂信封。

string str = "CountryName=Canada";
byte[] postBytes = Encoding.ASCII.GetBytes(str);
request.ContentType = "text";
request.ContentLength = postBytes.Length;
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);

使用SOAP 1.1:

编辑代码的这一行,

string _action = "http://www.webserviceX.NET/GetWeather";

替换为

string _action = "http://www.webservicex.net/globalweather.asmx";

多数民众赞成,享受:)

答案 1 :(得分:0)

我发现这个问题实际上是由请求xml中包含的空格引起的,我通过添加soapEvelop.PreserveWhitespace = true解决了这个问题;

   public static XmlDocument createSoapEnvelop(string cityName="", string countryName="")
    {
        XmlDocument soapEvelope = new XmlDocument();
        soapEvelope.PreserveWhitespace = true;
        soapEvelope.LoadXml(@"<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""><soap:Body><GetWeather xmlns=""http://www.webserviceX.NET""><CityName></CityName><CountryName>"+countryName+"</CountryName></GetWeather></soap:Body></soap:Envelope>");
        return soapEvelope;
    }