Reputation:
I´m trying to use a Webservice in a .Net Compact Framework 3.5 Project which has no WSDL and where I have to use HttpWebRequest. I´ve tried my code on 2 Devices and on the Emulator but I get everytime the same Exception and I really don´t get why!?
First, my code:
internal void SendSms()
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"https://username:[email protected]/RPC2");
req.Method = @"POST";
req.ContentType = @"text/xml";
req.ContentLength = Body.Length;
using (Stream stream = req.GetRequestStream())
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(Body);
}
using (Stream responseStream = req.GetResponse().GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
{
string result = reader.ReadToEnd();
}
}
In line "using (Stream stream = req.GetRequestStream())" I get the following exception and I can´t figure out why:
System.Net.WebException {"Could not establish connection to network."}
Stacktrace:
at System.Net.HttpWebRequest.finishGetRequestStream() at System.Net.HttpWebRequest.GetRequestStream() at SipMSGate.UI.MainFormController.SendSms() at SipMSGate.UI.Form1.menuItem1_Click(Object sender, EventArgs e) at System.Windows.Forms.MenuItem.OnClick(EventArgs e) at System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis, WM wm, Int32 wParam, Int32 lParam) at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam) at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam) at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain) at System.Windows.Forms.Application.Run(Form fm) at SipMSGate.Program.Main()
Status:
System.Net.WebExceptionStatus.ConnectFailure
I can use the Internet explorer on the Devices and on the Emulator, so I think that I have an internet Connection.
Any Idea what´s wrong or what I forget in my code?
Than you so much
twickl
Here is now the complete Code including Yakimych's Code that gives the xception on 2 Devices and the Emulator Images which all of them are having a connection to the Internet:
using System.Drawing;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Windows.Forms;
namespace httpreqTest
{
public partial class Form1 : Form
{
private HttpWebRequest _req;
private bool _ignoreCertificateErrors;
private string _errorMessage;
private const string Body =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><methodCall><methodName>samurai.SessionInitiate</methodName><params><param><value><struct><member><name>LocalUri</name><value><string></string></value></member><member><name>RemoteUri</name><value><string>01234556789</string></value></member><member><name>TOS</name><value><string>text</string></value></member><member><name>Content</name><value><string>This is a Test</string></value></member><member><name>Schedule</name><value><string></string></value></member></struct></value></param></params></methodCall>";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this._ignoreCertificateErrors = true;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(Body);
CreateWebRequestObject(@"https://user:[email protected]/RPC2");
_req.Method = @"POST";
_req.ContentType = @"text/xml";
_req.ContentLength = byte1.Length;
using (Stream stream = _req.GetRequestStream())
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(Body);
}
using (Stream responseStream = _req.GetResponse().GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
{
string result = reader.ReadToEnd();
}
}
public bool CreateWebRequestObject(string Url)
{
try
{
this._req = (HttpWebRequest)System.Net.WebRequest.Create(Url);
if (this._ignoreCertificateErrors)
ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
}
catch (Exception ex)
{
this._errorMessage = ex.Message;
return false;
}
return true;
}
/// <summary>
/// Internal object used to allow setting WebRequest.CertificatePolicy to
/// not fail on Cert errors
/// </summary>
internal class AcceptAllCertificatePolicy : ICertificatePolicy
{
public AcceptAllCertificatePolicy()
{
}
public bool CheckValidationResult(ServicePoint sPoint, X509Certificate cert, WebRequest wRequest, int certProb)
{
// *** Always accept
return true;
}
}
}
}
Upvotes: 0
Views: 10134
Reputation: 1
I got the same error. You have to call
WebResponse ws = request.GetResponse();
// do some stuff
ws.close();
With using(Stream responseStream = req.GetResponse().GetResponseStream())
, you create a WebResponse
, but you don't close it. On mobile devices it leads fast to a time-out exception.
Upvotes: 0
Reputation: 5414
You are passing the wrong value to the Content-Length header. It should be the length of the content in bytes not the count of unicode characters in the string (StreamWriter
also adds the UTF8 preamble). I recommend not using the preamble and converting the string to a byte array before setting the Content-Length header value. Also, passing the username and password using the req.Credentials
property might be a good idea.
internal void SendSms()
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"https://api.sipgate.net/RPC2");
req.Credentials = new NetworkCredential("username", "password");
req.Method = @"POST";
req.ContentType = @"text/xml";
byte[] data = Encoding.UTF8.GetBytes(Body);
req.ContentLength = data.Length;
using(Stream stream = req.GetRequestStream())
stream.Write(data, 0, data.Length);
using(Stream responseStream = req.GetResponse().GetResponseStream())
using(StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
{
string result = reader.ReadToEnd();
}
}
Upvotes: 4
Reputation: 54894
I don't think HTTP/HTTPS supports the same username password constructs in the URL as FTP does. If you are trying to do basic authentication you need to pass those in through the header. Try this:
req.Credentials = new NetworkCredential("username","password");
This will pass along the "Basic Authentication" credentials to the web host. You can read more about it here:
http://msdn.microsoft.com/en-us/library/system.net.networkcredential.aspx
Upvotes: 0
Reputation: 17752
Indeed, when using https, you need to validate the certificate. To do that, create an AcceptAllCertificatePolicy class and set the certificate policy BEFORE your code: ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
You can find a sample and the class code here: http://www.west-wind.com/weblog/posts/48909.aspx
See if this solves the problem.
Upvotes: 2