user99070
user99070

Reputation:

.Net CF / HttpWebRequest and a "WebException was unhandled"

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

Answers (4)

slowjack2k
slowjack2k

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

Pent Ploompuu
Pent Ploompuu

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

Nick Berardi
Nick Berardi

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

Yakimych
Yakimych

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

Related Questions