【问题标题】:.Net CF / HttpWebRequest and a "WebException was unhandled".Net CF / HttpWebRequest 和“未处理 WebException”
【发布时间】:2010-12-30 15:03:09
【问题描述】:

我正在尝试在没有 WSDL 且必须使用 HttpWebRequest 的 .Net Compact Framework 3.5 项目中使用 Web 服务。 我已经在 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 {“无法建立网络连接。”}

堆栈跟踪:

在 System.Net.HttpWebRequest.finishGetRequestStream() 在 System.Net.HttpWebRequest.GetRequestStream() 在 SipMSGate.UI.MainFormController.SendSms() 在 SipMSGate.UI.Form1.menuItem1_Click(对象发送者,EventArgs e) 在 System.Windows.Forms.MenuItem.OnClick(EventArgs e) 在 System.Windows.Forms.Menu.ProcessMnuProc(控制 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 个设备和模拟器图像上给出了异常,它们都连接到 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;
        }
    }
}

}

【问题讨论】:

  • 也许是 https 中的 (s) 导致了问题?您可能需要先验证证书,然后才能创建此类连接。
  • 完全不相关,但您不需要手动设置req.ContentLength
  • 嗯,只要我不设置内容长度,我就会得到一个异常,说内容长度不能为-1?!

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


【解决方案1】:

我遇到了同样的错误。你必须打电话

WebResponse ws = request.GetResponse();

// do some stuff

ws.close();

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

【讨论】:

    【解决方案2】:

    您将错误的值传递给 Content-Length 标头。它应该是 bytes 中内容的长度,而不是字符串中 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();
     }
    }
    

    【讨论】:

      【解决方案3】:

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

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

      这会将“基本身份验证”凭据传递给网络主机。您可以在此处阅读更多信息:

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

      【讨论】:

        【解决方案4】:

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

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

        看看这是否能解决问题。

        【讨论】:

        • 嗨,我试过你的代码,但它不能解决我的问题。我总体上得到了相同的异常。有什么想法吗?有没有办法检查这是否是认证问题。因为异常仍然是“无法建立与网络的连接”。虽然我在我的设备上建立了 Internet 连接。使用 2.0 和 3.5 Compact Framework 项目进行了尝试。
        • 首先,检查您是否可以进行常规的 http:// 连接。这将排除互联网连接问题。仅仅因为 IE 可以连接,并不意味着 .net 应用程序可以连接。
        猜你喜欢
        • 2015-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-23
        • 2013-10-24
        • 2010-10-08
        • 2017-06-04
        • 1970-01-01
        相关资源
        最近更新 更多