我们曾经学习过如何在Silverlight中用HttpWebRequest通讯。这里我们学习如何使用WebClient实现通讯。
一、什么是WebClient类
1、基本知识
WebClient类是Mircsoft在.NET框架下提供的向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法。通过这个类,大家可以在脱离浏览器的基础上模拟浏览器对互联网上的资源的访问和发送信息。它使人们使用起来更加简单方便,然而它也有先天不足的地方。那就是缺少对cookies/session的支持。
WebClient类为Silverlight插件提供了一整套的HTTP客户端功能,可以下载应用程序数据,比如XAML内容,附加的程序集或者视频图片等媒体文件。WebClient可以根据程序须要即时下载内容,可以异步呈现和使用下载的内容,而不是随HTML页面一起下载。
WebClient类提供了发起请求、监视请求的进度以及检索下载内容、上传数据到指定资源等功能。在Silverlight 2中,只能使用WebClient发起异步的请求,如开发一个视频播放应用程序,在应用程序加载时,选择开始请求每一部影片,使其加载到浏览器缓存中,这样可以避免缓冲延迟。
由于WebClient请求都是异步的,使用的是基于异步事件编程模型,大部分交互操作都是依靠事件处理来完成的,通常须要定义如下一个或者多个事件处理函数。
2、相关方法
将数据上载到资源的 WebClient 方法
OpenWriteAsync: 检索 Stream,它在不阻止调用线程的情况下以异步方式将数据发送到资源。
UploadStringAsync: 在不阻止调用线程的情况下,将 String 发送到资源。
从资源下载数据的 WebClient 方法
DownloadStringAsync: 在不阻止调用线程的情况下,从资源下载 String。
OpenReadAsync : 在不阻止调用线程的情况下,以异步方式从资源返回数据。
您可以使用 CancelAsync 方法取消尚未完成的异步操作。
3、两种工作方式:
A、以字符串形式下载和上传数据
使用WebClient可以以字符串形式下载数据,当请求一个指定地址的字符串时,调用DownloadStringAsync方法,操作完成后将触发DownloadStringCompleted事件,在该事件处理方法中能够接收到一个类型为DownloadStringCompletedEventArgs的参数,它的Result属性的类型为String,我们可以通过该属性来获得最终的字符串结果,它可以是一段普通的文本或一段XML文本等。
B、 以流形式下载和上传数据
使用WebClient同样可以以流形式下载数据,当请求下载的资源是一个流时,可调用OpenReadAsync方法,此操作完成后将触发OpenReadCompleted事件,在该事件处理方法中能够接收到一个类型为OpenReadCompletedEventArgs的参数,它的Result属性类型为Stream,使用此属性能够获取到最终的流结果。
二、示例如何实现通讯 (以字符串形式下载和上传数据)
新建Silverlight应用程序SLWebClient。如下图:
编写界面布局,XAML如下:
<
UserControl x:Class
=
"
SLWebClient.Page
"
xmlns
=
"
http://schemas.microsoft.com/winfx/2006/xaml/presentation
"
xmlns:x
=
"
http://schemas.microsoft.com/winfx/2006/xaml
"
Width
=
"
400
"
Height
=
"
400
"
>
<
StackPanel Height
=
"
400
"
Width
=
"
400
"
Orientation
=
"
Vertical
"
>
<
StackPanel Height
=
"
250
"
Width
=
"
400
"
Background
=
"
Bisque
"
>
<
TextBlock Text
=
"
以字符串形式下载数据
"
TextAlignment
=
"
Center
"
FontSize
=
"
16
"
Foreground
=
"
Red
"
></
TextBlock
>
<
Button x:Name
=
"
btnLoadCity
"
Content
=
"
加裁城市信息
"
Width
=
"
200
"
Click
=
"
btnLoadCity_Click
"
></
Button
>
<
Button x:Name
=
"
btnLoadWeather
"
Content
=
"
加裁天气信息
"
Width
=
"
200
"
Click
=
"
btnLoadWeather_Click
"
></
Button
>
<
TextBlock Text
=
"
信息加载如下..
"
TextAlignment
=
"
Center
"
Foreground
=
"
Green
"
>
</
TextBlock
>
<
ListBox x:Name
=
"
lstBxResult
"
Height
=
"
120
"
Width
=
"
350
"
>
</
ListBox
>
<
TextBlock x:Name
=
"
tbResult
"
Text
=
"
当前无内容
"
TextAlignment
=
"
Center
"
TextWrapping
=
"
Wrap
"
Width
=
"
300
"
Height
=
"
30
"
Foreground
=
"
Blue
"
></
TextBlock
>
</
StackPanel
>
<
StackPanel Width
=
"
400
"
Height
=
"
100
"
Background
=
"
Lavender
"
>
<
TextBlock Text
=
"
以字符串形式上传数据
"
TextAlignment
=
"
Center
"
FontSize
=
"
16
"
Foreground
=
"
Red
"
></
TextBlock
>
<
TextBox x:Name
=
"
txtBxUploadStr
"
Width
=
"
350
"
Height
=
"
40
"
Text
=
"
This is the Text Content come from Silverlight TextBox.
"
TextWrapping
=
"
Wrap
"
></
TextBox
>
<
Button x:Name
=
"
btnUploadText
"
Width
=
"
200
"
Height
=
"
25
"
Content
=
"
上传文本信息
"
Margin
=
"
6
"
Click
=
"
btnUploadText_Click
"
></
Button
>
</
StackPanel
>
</
StackPanel
>
</
UserControl
>
界面如下图:
在客户端,我们要完成两段代码:
i、向服务器端发出"下载字符串"请求,相关代码如下:
#region
以字符串形式下载信息
private
void
btnLoadCity_Click(
object
sender, RoutedEventArgs e)
{
GetInfomation(
"
city
"
);
}
private
void
btnLoadWeather_Click(
object
sender, RoutedEventArgs e)
{
GetInfomation(
"
weather
"
);
}
private
void
GetInfomation(
string
infoType)
{
//
string tranType = "Json";
string
tranType
=
"
TextStr
"
;
Uri endpoint
=
new
Uri(String.Format(
"
http://localhost:49417/WebClientDownHandler.ashx?infoType={0}&tranType={1}
"
, infoType, tranType));
WebClient client
=
new
WebClient();
client.DownloadStringCompleted
+=
new
DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(endpoint);
}
void
client_DownloadStringCompleted(
object
sender, DownloadStringCompletedEventArgs e)
{
string
RetStr
=
""
;
if
(e.Error
==
null
)
{
//
RetStr = "WebClient成功通讯";
RetStr
=
e.Result;
ShowGetRetList(RetStr);
}
else
{
RetStr
=
e.Error.Message;
}
this
.tbResult.Text
=
RetStr;
//
显示操作结果信息
}
//
把传递过来的字符串分解为字符串数组并显示在List控件中
private
void
ShowGetRetList(
string
retStr)
{
char
splitChar
=
'
:
'
;
//
定义字符串分隔符
this
.lstBxResult.Items.Clear();
//
先清空ListBox中的显示
string
[] retStrArray
=
retStr.Split(splitChar);
for
(
int
i
=
0
; i
<
retStrArray.Length; i
++
)
{
this
.lstBxResult.Items.Add(retStrArray[i]);
}
}
#endregion
ii、向服务器端发出"上传字符串"请求,相关代码如下:
#region
以字符串形式上传信息
private
void
btnUploadText_Click(
object
sender, RoutedEventArgs e)
{
//
要上传的文本数据
string
data
=
this
.txtBxUploadStr.Text.ToString();
Uri endpoint
=
new
Uri(
"
http://localhost:49417/WebClientUpLoadHandler.ashx
"
);
WebClient client
=
new
WebClient();
client.UploadStringCompleted
+=
new
UploadStringCompletedEventHandler(client_UploadStringCompleted);
client.UploadStringAsync(endpoint,
"
POST
"
, data);
}
void
client_UploadStringCompleted(
object
sender,UploadStringCompletedEventArgs e)
{
MessageBox.Show(e.Result);
}
#endregion
Page.xaml.cs全部代码如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Net;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Documents;
using
System.Windows.Input;
using
System.Windows.Media;
using
System.Windows.Media.Animation;
using
System.Windows.Shapes;
using
System.IO;
using
System.Text;
using
System.Runtime.Serialization.Json;
namespace
SLWebClient
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
以字符串形式下载信息#region 以字符串形式下载信息
private void btnLoadCity_Click(object sender, RoutedEventArgs e)
{
GetInfomation("city");
}
private void btnLoadWeather_Click(object sender, RoutedEventArgs e)
{
GetInfomation("weather");
}
private void GetInfomation(string infoType)
{
// string tranType = "Json";
string tranType = "TextStr";
Uri endpoint = new Uri(String.Format("http://localhost:49417/WebClientDownHandler.ashx?infoType={0}&tranType={1}", infoType, tranType));
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(endpoint);
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string RetStr = "";
if (e.Error == null)
{
//RetStr = "WebClient成功通讯";
RetStr = e.Result;
ShowGetRetList(RetStr);
}
else
{
RetStr = e.Error.Message;
}
this.tbResult.Text = RetStr; //显示操作结果信息
}
//把传递过来的字符串分解为字符串数组并显示在List控件中
private void ShowGetRetList(string retStr)
{
char splitChar = ':'; //定义字符串分隔符
this.lstBxResult.Items.Clear(); //先清空ListBox中的显示
string[] retStrArray = retStr.Split(splitChar);
for (int i = 0; i < retStrArray.Length; i++)
{
this.lstBxResult.Items.Add(retStrArray[i]);
}
}
#endregion
以字符串形式上传信息#region 以字符串形式上传信息
private void btnUploadText_Click(object sender, RoutedEventArgs e)
{
// 要上传的文本数据
string data = this.txtBxUploadStr.Text.ToString();
Uri endpoint = new Uri("http://localhost:49417/WebClientUpLoadHandler.ashx");
WebClient client = new WebClient();
client.UploadStringCompleted +=
new UploadStringCompletedEventHandler(client_UploadStringCompleted);
client.UploadStringAsync(endpoint, "POST", data);
}
void client_UploadStringCompleted(object sender,UploadStringCompletedEventArgs e)
{
MessageBox.Show(e.Result);
}
#endregion
}
}
在服务器端,我们要建立两个Handler
WebClientDownHandler.ashx :处理客户端的下载请求.
WebClientUpLoadHandler.ashx :处理客户端的上传请求
WebClientDownHandler.ashx --负责处理下载字符串请求的Handler代码如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Text;
using
System.IO;
namespace
SLWebClient.Web
{
public class WebClientHandler : IHttpHandler
{
CityLis字符串数组#region CityLis字符串数组
public static readonly string[] CityList = new string[]
{
"BeiJing",
"ChengDu",
"XiangGang",
"ChongQing",
"ShenZheng"
};
#endregion
WeatherList字符串数组#region WeatherList字符串数组
public static readonly string[] WeatherList = new string[]
{
"晴天",
"阴天",
"多云",
"小雨"
};
#endregion
处理客户端请求并返回处理结果#region 处理客户端请求并返回处理结果
public void ProcessRequest(HttpContext context)
{
//读取从客户端传递过来的参数
string infoTypeStr = context.Request.QueryString["infoType"].ToString();
string tranTypeStr = context.Request.QueryString["tranType"].ToString();
string retValueStr = "";
if (tranTypeStr == "TextStr")
{
//根据客户端传参判断应该从服务器端返回什么结果信息
switch (infoTypeStr)
{
case "city": retValueStr = combineStringArry(CityList); break; //返回city字符串数组
case "weather": retValueStr = combineStringArry(WeatherList); break; //返回weather字符串数组
}
}
context.Response.ContentType = "text/plain";
context.Response.Write(retValueStr);
}
#endregion
把字符串拼接成字符串数组并返回#region 把字符串拼接成字符串数组并返回
public string combineStringArry(string[] strArray)
{ //把字符串拼接成字符串数组并返回
string t = "";
char splitChar = ':'; //定义字符串数组中的分隔符
for (int i = 0; i < strArray.Length; i++)
{
if (i == strArray.Length - 1)
{
t = t + strArray[i].ToString();
}
else
{
t = t + strArray[i].ToString() + splitChar;
}
}
return t;
}
#endregion
public bool IsReusable
{
get
{
return false;
}
}
}
}
WebClientUpLoadHandler.ashx--负责处理上传字符串请求的Handler代码如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Text;
using
System.IO;
namespace
SLWebClient.Web
{
public class WebClientUpLoadHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//获取从Silverlight客户端传来的信息
int length = context.Request.ContentLength;
byte[] bytes = context.Request.BinaryRead(length);
string txtContent = Encoding.Default.GetString(bytes);
//从服务器端返回信息
context.Response.ContentType = "text/plain";
context.Response.Write("服务器端成功收到信息,文本内容是: " + txtContent);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
生成应用程序并运行,运行效果如下:
前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)