Reputation: 163
Hi guys i'm new to programming and trying learn web services please help me with this problem!
I'm trying to use httpWebRequest to post soap xml to http://www.webservicex.net/globalweather.asmx using the following xml with 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>
The issue here is if i leave CityName blank , it returns Data Not Found, however when i send the same xml using soap ui, the correct weather information can be returned because the WSDL http://www.webservicex.net/globalweather.asmx?WSDL states that CityName is optional.
Would appreciate if anyone could tell me how can i get this working.
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);
}
}
}
}
Upvotes: 0
Views: 2482
Reputation: 163
I have found out that this issue is actually caused by white spaces contained inside the request xml , i solved this issue by adding 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;
}
Upvotes: 0
Reputation: 1753
I can tell you where did you go wrong though i am not able to figure out where do you need to tweak your code. Please open your wsdl and see the service tag at end of wsdl. you will find 4 ports.
<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>
You are trying to execute GlobalWeatherHttpPost while you are providng your input as per GlobalWeatherSoap. That's the problem.. If you want to use httppost method then this would be your operation.
<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>
And you need to implement as per following binding,
<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>
Please modify your code accordingly.Refer input and output message format in your wsdl for this operation.
Editing your code correction: "however when i send the same xml using soap ui, the correct weather information can be returned because the WSDL http://www.webservicex.net/globalweather.asmx?WSDL states that CityName is optional."
In soapui, it will create rquest for only soap operations, not httpget and httppost.
To implement httppost: 1.Remove this
request.Headers.Add("SOAPAction", action);
2.Remove soap envelop creaation in your code.
3.while calling the post request in your code pass CityName=string&CountryName=string instead of soap envelope.
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);
Using SOAP 1.1:
Edit this line of your code,
string _action = "http://www.webserviceX.NET/GetWeather";
Replace with
string _action = "http://www.webservicex.net/globalweather.asmx";
Thats all, enjoy :)
Upvotes: 1