HttpWebRequest 是 .net 基类库中的一个类,在命名空间 System.Net 下面,用来使用户通过 HTTP 协议和服务器交互。 HttpWebRequest 对 HTTP 协议进行了完整的封装,程序使用 HTTP 协议和服务器交互主要是进行数据的提交,通常数据的提交是通过 GET 和 POST 两种方式来完成。
HttpWebRequest常用命令如下:
HttpWebRequest
-
对指定的 URI 发出请求
Create()
-
初始化一个 WebRequest
BeginGetResponse()
-
开始对指定 URI 资源做异步请求
EndGetResponse()
-
结束对指定 URI 资源做异步请求
HttpWebResponse
-
对指定的 URI 做出响应
GetResponseStream()
-
获取响应的数据流
需要注意的是: HttpWebRequest使用基于代理的异步编程模型,在HTTP响应返回时引发的HttpWebRequest回调不是在UI线程上返回的,因此在该回调中需要额外代码处理UI,否则就会产生"跨线程访问无效"错误。
在本例中我们将通过两种方式来编写处理UI的额外代码,即解决"跨线程访问无效"的问题(当然是在Client成功向Server端发送信息,以及Server端成功向Client端传回数据的前提下)。
注:在实际应用时,如果我们要更新UI,则我们常使用silverlight支持的另一种发送HTTP请示的方式即WebClient方式,此方式与HttpWebRequest不同处在于,WebClient方式使用基于事件的异步编程模型,在HTTP响应返回时引发的WebClient回调是在UI线程中调用的,因此可用于更新UI元素的属性,例如把HTTP响应中的数据绑定到UI的指定控件上进行显示。
另注:在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型,有以下三种类型:
application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。
multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。
text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
本例,我们将在两个按钮中分别采用"application/x-www-form-urlencoded"和"text/plain"方式来编码提交数据到服务器端
新建Silverlight应用程序
程序用户界面如下:
如图所示,界面上有两个按钮,两个按钮的后台操作分别为:
按钮"用Thread配合AsynchronazationContext解决跨线程访问无效问题"--当点击后
1、将把字符串"This Msg Come From Client"传递到服务器端
2、uri地址是指定的asp页面(此处是Default.aspx页面)
3、编码方式采用text/plain
4、服务器端接收到客户端传来的数据后,用StreamReader把传参接收下来,并在此基础上加入服务器端数据并返回
5、客户端采用"Thread配合AsynchronazationContext方式"把服务器端返回的数据显示在UI控件上
按钮"用Socket配合AsynchronazationContext解决跨线程访问无效问题"--当点击后
1、将把字符串"This Msg Come From Client"传递到服务器端
2、uri地址是指定的Handler(此处是ServerHandler.ashx)
3、编码方式采用application/x-www-form-urlencoded
4、服务器端接收到客户端传来的数据后,用Params.Get()方法把传参接收下来,并在此基础上加入服务器端数据并返回
5、客户端采用"Socket配合AsynchronazationContext解决跨线程访问无效问题"把服务器端返回的数据显示在UI控件上
以下是代码内容:
Page.xaml界面设计代码
Code
<UserControl x:Class="SLHttpWebRequest.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<StackPanel x:Name="layoutRoot" Background="Wheat" VerticalAlignment="Center">
<TextBlock Text="HttpWebRequest 通讯示例 " TextAlignment="Center" FontSize="18" Foreground="red"></TextBlock>
<TextBlock Text="用Thread配合AsynchronazationContext解决跨线程访问无效问题" TextAlignment="Center" Foreground="Green"></TextBlock>
<TextBlock x:Name="lsResultThread"></TextBlock>
<Button Content="ClickMe-Thread" Click="ClickThread"/>
<TextBlock Text="用Socket配合AsynchronazationContext解决跨线程访问无效问题" TextAlignment="Center" Foreground="Green"></TextBlock>
<TextBlock x:Name="lsResultSocket"/>
<Button Click="ClicksSocket" Content="ClickMe-Socket" />
</StackPanel>
</UserControl>
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.Threading;
//
解决线程同步问题
using
System.Net.Sockets;

namespace
SLHttpWebRequest

{
public partial class Page : UserControl

{

System.Net.Sockets.Socket socket;
private SynchronizationContext currentContext;

string clientMsg = "This Msg Come From Client";
string resStr = "";

public Page()

{
InitializeComponent();
this.currentContext = SynchronizationContext.Current;
}


用Thread配合AsynchronazationContext解决跨线程访问无效问题&text/plain传参"#region 用Thread配合AsynchronazationContext解决跨线程访问无效问题&text/plain传参"


ClickThread#region ClickThread
private void ClickThread(object sender, RoutedEventArgs e)

{
Uri endpoint = new Uri("http://localhost:32767/Default.aspx");

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint);
request.Method = "POST";
request.ContentType = "text/plain";
request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);
}
#endregion


RequestReady#region RequestReady
void RequestReady(IAsyncResult asyncResult)

{
WebRequest request = asyncResult.AsyncState as WebRequest;
Stream requestStream = request.EndGetRequestStream(asyncResult);

using (StreamWriter writer = new StreamWriter(requestStream))

{
writer.Write(String.Format("clientMsg={0}", clientMsg));
writer.Flush();
}

request.BeginGetResponse(new AsyncCallback(ResponseReady), request);
}

#endregion


ResponseReady#region ResponseReady
void ResponseReady(IAsyncResult asyncResult)

{
WebRequest request = asyncResult.AsyncState as WebRequest;
WebResponse response = request.EndGetResponse(asyncResult);

using (Stream responseStream = response.GetResponseStream())

{
StreamReader reader = new StreamReader(responseStream);
string paramStr = reader.ReadToEnd();
resStr = paramStr;
Thread mythread = new Thread(new ThreadStart(AcrossThread));
mythread.Start();


}
}
#endregion


AcrossThread#region AcrossThread
private void AcrossThread()

{
currentContext.Post(result =>

{
lsResultThread.Text = resStr; //在此处修改UI内容

}, null);
}
#endregion

#endregion


用Socket配合AsynchronazationContext解决跨线程访问无效问题&application/x-www-form-urlencoded方式传参#region 用Socket配合AsynchronazationContext解决跨线程访问无效问题&application/x-www-form-urlencoded方式传参


ClicksSocket#region ClicksSocket
private void ClicksSocket(object sender, RoutedEventArgs e)

{
socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs()

{
RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4502)
};

socketArgs.Completed += OnOperationCompleted;
socketArgs.UserToken = socket;
socket.ConnectAsync(socketArgs);
}
#endregion


OnOperationCompleted#region OnOperationCompleted
void OnOperationCompleted(object sender, SocketAsyncEventArgs e)

{
Uri endpoint = new Uri("http://localhost:32767/ServerHandler.ashx");

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint);

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.BeginGetRequestStream(new AsyncCallback(RequestReadySocket), request);

}

#endregion


RequestReadySocket#region RequestReadySocket
void RequestReadySocket(IAsyncResult asyncResult)

{
WebRequest request = asyncResult.AsyncState as WebRequest;
Stream requestStream = request.EndGetRequestStream(asyncResult);

using (StreamWriter writer = new StreamWriter(requestStream))

{
writer.Write(String.Format("clientMsg={0}", clientMsg));
writer.Flush();
}

request.BeginGetResponse(new AsyncCallback(ResponseReadySocket), request);
}
#endregion


ResponseReadySocket#region ResponseReadySocket
void ResponseReadySocket(IAsyncResult asyncResult)

{
WebRequest request = asyncResult.AsyncState as WebRequest;
WebResponse response = request.EndGetResponse(asyncResult);

using (Stream responseStream = response.GetResponseStream())

{
StreamReader reader = new StreamReader(responseStream);
string paramStr = reader.ReadToEnd();
resStr = paramStr;
currentContext.Post(ShowReturnStr, resStr);
}
}
#endregion


ShowReturnStr#region ShowReturnStr
void ShowReturnStr(object str)

{
this.lsResultSocket.Text = str.ToString(); //在此处修改UI内容

}
#endregion

#endregion


}
}
Default.aspx代码
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text; //使用StringBuilder
using System.IO; //使用Stream
namespace SLHttpWebRequest.Web
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder("Message From Server:");
if (Request.ContentType == "text/plain") //首先判断ContentType是不是"text/plain"方式,如果是,则采用StreamReader类来获取Client端传来的参数
{
if (Request.InputStream == null || Request.InputStream.Length <= 0)
{
sb.Append("Sorry, There is No Message Come From Client");
}
else
{
using (Stream inputStream = Request.InputStream) //接收从Client端传来的参数,由于ContentType是"text/plain",所以用StreamReader来取得对应参数
{
using (StreamReader sr = new StreamReader(inputStream))
{
sb.Append(sr.ReadToEnd());
}
}
}
}
Response.Write(sb.ToString());
Response.End();
}
}
}
ServerHandler.ashx代码
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services; //使用[WebService]等
using System.IO;
using System.Text;
using System.Threading;
namespace SLHttpWebRequest.Web
{
///// <summary>
///// $codebehindclassname$ 的摘要说明
///// </summary>
//[WebService(Namespace = "http://tempuri.org/")]
//[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class ServerHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
StringBuilder sb = new StringBuilder("Message From Server:");
if (context.Request.ContentType == "application/x-www-form-urlencoded")
{//首先判断ContentType是不是"application/x-www-form-urlencoded"方式,如果是,则采用Params.Get方法来获取Client端传来的参数
try
{
string paramStr = context.Request.Params.Get("clientMsg"); //接收从Client端传来的参数,由于ContentType是"application/x-www-form-urlencoded",所以用Params.Get方法来取得对应参数
sb.Append(paramStr);
}
catch { }
}
context.Response.Write(sb.ToString());
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
运行后效果如下
前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)