网络和通信 - Silverlight 中的 HTTP 通信和安全
Silverlight 支持几种使用 HTTP/HTTPS 的方案。虽然可以使用多种方式和技术执行 HTTP 调用,但是下表描述的是针对这些 HTTP 通信方案的建议方法
确定应由浏览器还是客户端来执行应用程序的 HTTP 处理后,应在创建任何 Web 请求之前指定该处理。然后可以通过使用客户端代理类或自己构造调用来执行 HTTP 调用
使用代理类
创建 HTTP 请求
如果您希望自己执行 HTTP 调用,可以使用以下在 System.Net 命名空间中找到的类。
通过这些类,您可以执行 GET 和 POST 请求并在某些情况下允许使用请求标头。此外,可以配置这些类以在 GET 请求上启用渐进式下载。
WebClient 类
WebClient 类提供了一个基于事件的简单模型,使您可以下载和上载流和字符串。如果不希望使用代理类,那么 WebClient 是个不错的选择。通常,此类易于使用,但为自定义通过网络发送的消息而提供的选项较少。
若要使用 WebClient 执行 POST 请求并上载资源文件或字符串,请使用以下方法之一。
可以通过设置 WebClient.Headers 属性对请求设置标头。必须根据客户端访问策略文件允许请求标头
// Create the web client.
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 的渐进式下载,请将 AllowReadStreamBuffering 属性设置为 false。
HttpWebRequest 类和 HttpWebResponse 类
HttpWebRequest 类和 HttpWebResponse 类比 WebClient 支持更复杂的通信方案。可以按照 .NET Framework 异步模式使用 HttpWebRequest 和 HttpWebResponse 执行请求。使用 IAsyncResult 可提供异步请求和响应之间的连接。始终对新的非 UI 线程调用 HttpWebRequest 委托,这意味着如果计划在 UI 中使用响应,则需要调用回 UI 线程。可以通过检索当前的 SynchronizationContext 来执行此操作。
SynchronizationContext syncContext;
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;
}