.Net CF / HttpWebRequest和“WebException未处理”

时间:2009-12-28 22:48:36

标签: c# windows windows-mobile compact-framework httpwebrequest

我试图在.Net Compact Framework 3.5项目中使用Web服务,该项目没有WSDL,我必须使用HttpWebRequest。 我在2台设备和模拟器上尝试了我的代码,但每次都得到相同的异常,我真的不明白为什么!?

首先,我的代码:

internal void SendSms()
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"https://username:password@api.sipgate.net/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();
        }
    }

在行中“使用(Stream stream = req.GetRequestStream())”我得到以下异常,我无法找出原因:

System.Net.WebException {“无法建立与网络的连接。”}

堆栈跟踪:

at System.Net.HttpWebRequest.finishGetRequestStream()    在System.Net.HttpWebRequest.GetRequestStream()    在SipMSGate.UI.MainFormController.SendSms()    在SipMSGate.UI.Form1.menuItem1_Click(Object sender,EventArgs e)    在System.Windows.Forms.MenuItem.OnClick(EventArgs e)    在System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis,WM wm,Int32 wParam,Int32 lParam)    在System.Windows.Forms.Form.WnProc(WM wm,Int32 wParam,Int32 lParam)    在System.Windows.Forms.Control._InternalWnProc(WM wm,Int32 wParam,Int32 lParam)    在Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)    在System.Windows.Forms.Application.Run(Form fm)    在SipMSGate.Program.Main()

状态:

System.Net.WebExceptionStatus.ConnectFailure

我可以在设备和模拟器上使用Internet Explorer,所以我认为我有一个互联网连接。

我的代码中有什么错误或遗忘的内容?

比你这么多

twickl

现在是完整的代码,包括Yakimych的代码,它给出了2个设备上的xception和模拟器映像,它们都连接到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:pass@api.sipgate.net/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;
        }
    }
}

}

5 个答案:

答案 0 :(得分:5)

您将错误的值传递给Content-Length标头。它应该是字节中内容的长度而不是字符串中的unicode字符数(StreamWriter也会添加UTF8前导码)。我建议在设置Content-Length标头值之前不要使用前导码并将字符串转换为字节数组。此外,使用req.Credentials属性传递用户名和密码可能是个好主意。

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();
 }
}

答案 1 :(得分:3)

实际上,使用https时,您需要验证证书。为此,请创建一个AcceptAllCertificatePolicy类,并在代码之前设置证书策略:ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();

您可以在此处找到示例和类代码: http://www.west-wind.com/weblog/posts/48909.aspx

看看这是否解决了这个问题。

答案 2 :(得分:1)

你的内容类型不应该是text / xml ??

答案 3 :(得分:1)

我不认为HTTP / HTTPS支持URL中与FTP相同的用户名密码构造。如果您尝试进行基本身份验证,则需要通过标头传递这些身份验证。试试这个:

req.Credentials = new NetworkCredential("username","password");

这会将“基本身份验证”凭据传递给Web主机。你可以在这里阅读更多相关信息:

http://msdn.microsoft.com/en-us/library/system.net.networkcredential.aspx

答案 4 :(得分:0)

我得到了同样的错误。你必须致电

WebResponse ws = request.GetResponse();

// do some stuff

ws.close();

使用using(Stream responseStream = req.GetResponse().GetResponseStream()),您可以创建WebResponse,但不要关闭它。在移动设备上,它可以快速导致超时异常。