我试图在.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;
}
}
}
}
答案 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
,但不要关闭它。在移动设备上,它可以快速导致超时异常。