在开发工作中,经常需要调用外部的接口,比如调用支付宝的接口、调用微信支付的接口、等等。这些接口一般都是以HTTP的形式对外开放的。
.NET Framework提供了用于执行HTTP请求的类,本文将介绍如何使用C#调用外部提供的HTTP接口。
在.NET中,在 System.Net
命名空间下有两个类:HttpWebRequest、HttpWebResponse
,这两个类可用来访问Web服务器上的资源。通常情况下,还需要用到System.Web
命名空间。System.Web命名空间下有一个HttpUtility
类,它提供了对HTML和URL编码和解码字符串的方法。
HTTP接口最常见的输出格式是JSON,另外,XML也是一种常见的格式,当然也可以是其它的格式,这取决于接口提供者。需要说明的是,.NET Framework广泛支持以XML格式读取和操作数据。
当然,上面提到的几个类不仅可用到调用HTTP接口,它们还可用来访问任意Web服务器上的资源。
简单的GET请求
下面这个示例请求一个URL,然后将获取到的数据打印出来:
using System;
using System.IO;
using System.Net;
using System.Text;
// 创建一个Web请求
HttpWebRequest request = WebRequest.Create("http://google.com") as HttpWebRequest;
// 获取Web服务器输出的数据
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// 取得输出流
StreamReader reader = new StreamReader(response.GetResponseStream());
Console.WriteLine(reader.ReadToEnd());
}
简单的POST请求
有些时候,某些API接口会要求你使用POST的方式访问。发送POST请求时,需将数据写入随请求一起发送的流中。
using System.Web;
Uri address = new Uri("http://face2face.net.cn/submitnews");
// 创建Web请求
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
// 设置以POST方式发送请求
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// 需要传递给接口的参数
string tit = "这是新闻标题";
string context = "这是新闻内容";
StringBuilder data = new StringBuilder();
data.Append("tit=" + HttpUtility.UrlEncode(tit));
data.Append("&context=" + HttpUtility.UrlEncode(context));
data.Append("&query=" + HttpUtility.UrlEncode(query));
// 将参数转为byte数组
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString());
// 设置请求头内容的长度
request.ContentLength = byteData.Length;
// 将参数写入请求流
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
// 获取Web服务器输出的数据
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// 取得输出流
StreamReader reader = new StreamReader(response.GetResponseStream());
// 打印获取到的数据
Console.WriteLine(reader.ReadToEnd());
}
HTTP认证请求
某些Web服务器提供的接口虽然是对外开放的,但是却要求通过身份认证,并不是随便可访问的。通过向请求添加NetworkCredentials实例可以轻松完成此操作。
// 创建Web请求
HttpWebRequest request = WebRequest.Create("http://facebook.com/editphoto") as HttpWebRequest;
// 增加身份认证信息到Web请求
request.Credentials = new NetworkCredential("username", "password");
// 获取Web服务器输出的数据
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// 取得输出流
StreamReader reader = new StreamReader(response.GetResponseStream());
// 打印取到的数据
Console.WriteLine(reader.ReadToEnd());
}
错误处理
并不是每次HTTP请求都能正常完成的。比如:网络异常、Web服务器异常、或者Web服务器认为该请求是错误或无效的,等等,都有可能造成HTTP请求失败。
当网络异常、Web服务器异常时,可通过捕获异常来处理。若是Web服务器正常处理了,但它认为此请求不能正常完成任务,那么我们就要根据此接口的文档来进行处理。通常,Web服务器会以HTTP状态码的方式告诉请求者处理结果。当然,具体是何种形式,要以接口提供者的文档为准。
如果Web服务器没有返回状态码200,请求超时或网络故障,则调用HttpRequest.GetResponse
将引发异常。重定向会被自动处理。
下面是一个比较完整的示例,获取Web服务器上的数据,并对HTTP错误码做了基本的处理。
public static void PrintSource(Uri address)
{
HttpWebRequest request;
HttpWebResponse response = null;
StreamReader reader;
StringBuilder sbSource;
if (address == null) {
throw new ArgumentNullException("address");
}
try
{
// 创建并初始化Web请求
request = WebRequest.Create(address) as HttpWebRequest;
request.UserAgent = ".NET Sample";
request.KeepAlive = false;
// 请求的超时时长为15秒
request.Timeout = 15 * 1000;
// 获取Web服务器输出的数据
response = request.GetResponse() as HttpWebResponse;
if (request.HaveResponse == true && response != null)
{
// 取得输出流
reader = new StreamReader(response.GetResponseStream());
// 将输出的数据放入StringBuilder
sbSource = new StringBuilder(reader.ReadToEnd());
// 打印取得的数据
Console.WriteLine(sbSource.ToString());
}
}
catch (WebException wex)
{
// 如果HTTP状态码不是200,处理异常
if (wex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)wex.Response)
{
Console.WriteLine(
"The server returned '{0}' with the status code {1} ({2:d}).",
errorResponse.StatusDescription, errorResponse.StatusCode,
errorResponse.StatusCode);
}
}
}
finally
{
if (response != null) { response.Close(); }
}
}