Silverlight 支持几种使用 HTTP/HTTPS 的方案。虽然可以使用多种方式和技术执行 HTTP 调用,但是下表描述的是针对这些 HTTP 通信方案的建议方法
执行 HTTP 调用的选项
确定应由浏览器还是客户端来执行应用程序的 HTTP 处理后,应在创建任何 Web 请求之前指定该处理。然后可以通过使用客户端代理类或自己构造调用来执行 HTTP 调用
使用代理类
如果要与 SOAP、WCF 或 ASP.NET AJAX Web 服务进行通信,可以基于 Web 服务元数据创建一个代理类并使用该代理与 Web 服务进行通信。Silverlight 使用 Windows Communication Foundation (WCF) 功能创建代理并通过 HTTP 发送 SOAP 1.1 消息。如果使用 Visual Studio,可以右击您的 Silverlight 项目,选择"添加服务引用"来自动创建代理。该代理为您创建消息并处理网络通信。
创建 HTTP 请求
如果您希望自己执行 HTTP 调用,可以使用以下在 System.Net 命名空间中找到的类。
-
WebClient
-
HttpWebRequest 和HttpWebResponse
通过这些类,您可以执行 GET 和 POST 请求并在某些情况下允许使用请求标头。此外,可以配置这些类以在 GET 请求上启用渐进式下载。
WebClient 类
WebClient 类提供了一个基于事件的简单模型,使您可以下载和上载流和字符串。如果不希望使用代理类,那么 WebClient 是个不错的选择。通常,此类易于使用,但为自定义通过网络发送的消息而提供的选项较少。
若要使用 WebClient 执行 POST 请求并上载资源文件或字符串,请使用以下方法之一。
-
WebClient.OpenWriteAsync
-
WebClient.UploadStringAsync
可以通过设置 WebClient.Headers 属性对请求设置标头。必须根据客户端访问策略文件允许请求标头
WebClient client = new WebClient();
public Page()
{
InitializeComponent();
// Associate the web client with a handler for its
// UploadStringCompleted event.
client.UploadStringCompleted +=
new UploadStringCompletedEventHandler(client_UploadStringCompleted);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// Create the request.
string postRequest = "<entry xmlns='http://www.w3.org/2005/Atom'>"
+ "<title type='text'>New Restaurant</title>"
+ "<content type='xhtml'>"
+ " <div xmlns='http://www.w3.org/1999/xhtml'>"
+ " <p>There is a new Thai restaurant in town!</p>"
+ " <p>I ate there last night and it was <b>fabulous</b>.</p>"
+ " <p>Make sure and check it out!</p>"
+ " </div>"
+ " </content>"
+ " <author>"
+ " <name>Pilar Ackerman</name>"
+ " <email>packerman@contoso.com</email>"
+ " </author>"
+ "</entry>";
// Sent the request to the specified URL.
client.UploadStringAsync(new Uri("http://blogs.contoso.com/post-create?blogID=1234",
UriKind.Absolute), postRequest);
}
// Event handler for the UploadStringCompleted event.
void client_UploadStringCompleted(object sender,
UploadStringCompletedEventArgs e)
{
// Output the response.
if (e.Error != null)
tb1.Text = e.Error.Message;
else
tb1.Text = e.Result;
}
若要使用 WebClient 执行 GET 请求来检索字符串或其他资源文件,请使用以下方法之一。
-
WebClient.OpenReadAsync
-
WebClient.DownloadStringAsync
若要启用 WebClient 的渐进式下载,请将 AllowReadStreamBuffering 属性设置为 false。
HttpWebRequest 类和 HttpWebResponse 类
HttpWebRequest 类和 HttpWebResponse 类比 WebClient 支持更复杂的通信方案。可以按照 .NET Framework 异步模式使用 HttpWebRequest 和 HttpWebResponse 执行请求。使用 IAsyncResult 可提供异步请求和响应之间的连接。始终对新的非 UI 线程调用 HttpWebRequest 委托,这意味着如果计划在 UI 中使用响应,则需要调用回 UI 线程。可以通过检索当前的 SynchronizationContext 来执行此操作。
private void Button_Click(object sender, RoutedEventArgs e)
{
// Grab SynchronizationContext while on UI Thread
syncContext = SynchronizationContext.Current;
// Create request
HttpWebRequest request =
WebRequest.Create(new Uri("http://blogs.contoso.com/post-create?blogID=1234",
UriKind.Absolute))
as HttpWebRequest;
request.Method = "POST";
// Make async call for request stream. Callback will be called on a background thread.
IAsyncResult asyncResult =
request.BeginGetRequestStream(new AsyncCallback(RequestStreamCallback), request);
}
string statusString;
private void RequestStreamCallback(IAsyncResult ar)
{
HttpWebRequest request = ar.AsyncState as HttpWebRequest;
request.ContentType = "application/atom+xml";
Stream requestStream = request.EndGetRequestStream(ar);
StreamWriter streamWriter = new StreamWriter(requestStream);
streamWriter.Write("<entry xmlns='http://www.w3.org/2005/Atom'>"
+ "<title type='text'>New Restaurant</title>"
+ "<content type='xhtml'>"
+ " <div xmlns='http://www.w3.org/1999/xhtml'>"
+ " <p>There is a new Thai restaurant in town!</p>"
+ " <p>I ate there last night and it was <b>fabulous</b>.</p>"
+ " <p>Make sure and check it out!</p>"
+ " </div>"
+ " </content>"
+ "<author>"
+ " <name>Pilar Ackerman</name>"
+ " <email>packerman@contoso.com</email>"
+ " </author>"
+ "</entry>");
// Close the stream.
streamWriter.Close();
// Make async call for response. Callback will be called on a background thread.
request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
}
private void ResponseCallback(IAsyncResult ar)
{
HttpWebRequest request = ar.AsyncState as HttpWebRequest;
WebResponse response = null;
try
{
response = request.EndGetResponse(ar);
}
catch (WebException we)
{
statusString = we.Status.ToString();
}
catch (SecurityException se)
{
statusString = se.Message;
if (statusString == "")
statusString = se.InnerException.Message;
}
// Invoke onto UI thread
syncContext.Post(ExtractResponse, response);
}
private void ExtractResponse(object state)
{
HttpWebResponse response = state as HttpWebResponse;
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
StreamReader responseReader = new StreamReader(response.GetResponseStream());
tb1.Text = response.StatusCode.ToString() +
" Response: " + responseReader.ReadToEnd();
}
else
tb1.Text = "Post failed: " + statusString;
}