一步一步学Silverlight 2系列(13):数据与通信之WebRequest

概述

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章带您快速进入Silverlight 2开发。

本文将简单介绍在Silverlight 2中如何使用WebRequest进行数据的提交和获取。

简单示例

在本文中,我们仍然使用在一步一步学Silverlight 2系列(12):数据与通信之WebClient中用过的示例,只不过稍微做一点小的改动,使用WebRequest提交书籍编号数据,并根据书籍号返回价格信息。最终运行的结果如下图:

TerryLee_Silverlight2_0062

编写界面布局,XAML如下:

<Grid Background="#46461F">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="40"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Border Grid.Row="0" Grid.Column="0" CornerRadius="15"
            Width="240" Height="36"
            Margin="20 0 0 0" HorizontalAlignment="Left">
        <TextBlock Text="书籍列表" Foreground="White"
                   HorizontalAlignment="Left" VerticalAlignment="Center"
                   Margin="20 0 0 0"></TextBlock>
    </Border>
    <ListBox x:Name="Books" Grid.Row="1" Margin="40 10 10 10"
             SelectionChanged="Books_SelectionChanged">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Name}" Height="32"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <Border Grid.Row="2" Grid.Column="0" CornerRadius="15"
            Width="240" Height="36" Background="Orange"
            Margin="20 0 0 0" HorizontalAlignment="Left">
        <TextBlock x:Name="lblPrice" Text="价格:" Foreground="White"
                   HorizontalAlignment="Left" VerticalAlignment="Center"
                   Margin="20 0 0 0"></TextBlock>
    </Border>
</Grid>
编写HttpHandler,注意我使用了context.Request.Form["No"],在后面我们将使用WebRequest在RequestReady方法中将数据写入请求流:
public class BookHandler : IHttpHandler
{
    public static readonly string[] PriceList = new string[] { 
        "66.00",
        "78.30",
        "56.50",
        "28.80",
        "77.00"
    };
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write(PriceList[Int32.Parse(context.Request.Form["No"])]);
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

在界面加载时绑定书籍列表,关于数据绑定可以参考一步一步学Silverlight 2系列(11):数据绑定

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    List<Book> books = new List<Book>() { 
        new Book("Professional ASP.NET 3.5"),
        new Book("ASP.NET AJAX In Action"),
        new Book("Silverlight In Action"),
        new Book("ASP.NET 3.5 Unleashed"),
        new Book("Introducing Microsoft ASP.NET AJAX")
    };

    Books.ItemsSource = books;
}

接下来在SelectionChanged事件中实现用户选择书籍时,我们使用WebRequest提交书籍编号,并且获得价格数据,仍然采用异步模式,提供RequestReady和ResponseReady两个回调函数:

private string bookNo;

void Books_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    bookNo = Books.SelectedIndex.ToString();

    Uri endpoint = new Uri("http://localhost:49955/BookHandler.ashx");

    WebRequest request = WebRequest.Create(endpoint);
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);
    request.BeginGetResponse(new AsyncCallback(ResponseReady), request); 
}

实现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("No={0}", bookNo));
        writer.Flush();
    }
}

实现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);
        lblPrice.Text = "价格:" + reader.ReadToEnd();
    }
}

最后运行的结果如下:

TerryLee_Silverlight2_0059

用户选择一本书籍后,将显示其价格:

TerryLee_Silverlight2_0062

结束语

本文简单介绍了在Silverlight 2中如何使用WebRequest提交和获取数据,你可以从这里下载示例程序。

下一篇:一步一步学Silverlight 2系列(14):数据与通信之WCF

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Tag标签: Silverlight
posted @ 2008-03-09 17:12 TerryLee 阅读(5821) 评论(42)  编辑 收藏 所属分类: Silverlight

  回复  引用  查看    
#1楼 2008-03-09 21:29 | Q.Lee.lulu      
13篇看完收工!
收获不少,期待后作.....
  回复  引用  查看    
#2楼 [楼主]2008-03-09 21:36 | TerryLee      
@Q.Lee.lulu
一会儿就发第14篇,很快就完:)
  回复  引用  查看    
#3楼 2008-03-10 00:30 | TT.Net      
写的速度真够快的啊~
  回复  引用  查看    
#4楼 [楼主]2008-03-10 08:52 | TerryLee      
@TT.Net
:)
  回复  引用    
#5楼 2008-03-12 18:59 | 高 [未注册用户]
System.Security.SecurityException”类型的异常在 System.Windows.dll 中发生,但未在用户代码中进行处理

其他信息: Security error.

这个是什么问题,能否解决?
thanks
  回复  引用    
#6楼 2008-03-12 19:02 | 高 [未注册用户]
fsafafafa
  回复  引用  查看    
#7楼 [楼主]2008-03-12 20:20 | TerryLee      
@高
什么时候报的这个错误?
  回复  引用    
#8楼 2008-03-12 21:53 | 高 [未注册用户]
测试webrequest的时候就是出现这个错。
调试你的代码也是出现这个错。
不知道什么原因?


  回复  引用    
#9楼 2008-03-12 21:55 | 高 [未注册用户]
request.BeginGetResponse(new AsyncCallback(ResponseReady), request);

就是这个代码出错!
  回复  引用    
#10楼 2008-03-13 11:16 | JeffreyChen [未注册用户]
太快了,跟不上呀,呵...
  回复  引用  查看    
#11楼 [楼主]2008-03-13 12:57 | TerryLee      
@高
我不太清楚是哪儿的问题,上面的代码我测试过,没有问题
  回复  引用  查看    
#12楼 [楼主]2008-03-13 12:57 | TerryLee      
@JeffreyChen
:)
  回复  引用  查看    
#13楼 2008-03-21 17:08 | 笑煞天      
我测试的时候也报Server Error.一样的错误.
  回复  引用  查看    
#14楼 [楼主]2008-03-21 22:17 | TerryLee      
@笑煞天
下载示例中的代码运行也报错这个错误吗?
  回复  引用  查看    
#15楼 2008-04-23 21:24 | John Rambo      
为什么我找不到[System]System.Net.WebRequest类?
  回复  引用  查看    
#16楼 2008-05-08 22:13 | 凯锐      

--引用--------------------------------------------------
John Rambo: 为什么我找不到[System]System.Net.WebRequest类?
--------------------------------------------------------
手工加一遍System.Net就可以了,不知是什么原因!!
  回复  引用  查看    
#17楼 2008-06-22 18:28 | 飄lá┽蕩去      
beta2在Stream requestStream = request.EndGetRequestStream(asyncResult);会报错。其会直接执行HttpHandler里的方法,但是参数根本就没写进去。

  回复  引用    
#18楼 2008-07-01 10:09 | Fisker Shao [未注册用户]
--引用--------------------------------------------------
飄l&#225;┽蕩去: beta2在Stream requestStream = request.EndGetRequestStream(asyncResult);会报错。其会直接执行HttpHandler里的方法,但是参数根本就没写进去。

--------------------------------------------------------

我跟踪调试以后也遇到相同问题,但不知道是不是因为beta2的问题。

  回复  引用  查看    
#19楼 [楼主]2008-07-01 10:16 | TerryLee      
@Fisker Shao
在Beta 2中是有变化!
  回复  引用    
#20楼 2008-07-04 22:54 | botsing [未注册用户]
--引用--------------------------------------------------
TerryLee: @Fisker Shao
在Beta 2中是有变化!
--------------------------------------------------------
我也是遇到了这个问题,那在beta2中这个问题有没有解决方法呢?
  回复  引用    
#21楼 2008-07-07 16:34 | JanIvan [未注册用户]
写的很好,很容易看明白!例子简单,比较全面!
希望楼主能加入点自己的理解,这样我们可以更深入的理解SL.
  回复  引用  查看    
#22楼 [楼主]2008-07-08 16:13 | TerryLee      
@JanIvan
呵呵,过奖

可惜由于版本的升级,这里的文章有些会出错

更深入的分析在后面我会写一些文章:)
  回复  引用    
#23楼 2008-07-23 14:12 | chenyang22 [未注册用户]
测试过了,下载源代码下来也报错!
  回复  引用  查看    
#24楼 [楼主]2008-07-23 22:20 | TerryLee      
@chenyang22
不知道你用的是哪个版本的?

这里的源代码是基于Silverlight 2 Beta 1的,另外由于源代码太大,删除了引用的程序集,请先看清楚报什么错误,再说好不好!
  回复  引用  查看    
#25楼 2008-07-27 17:51 | 木野狐(Neil Chen)      
这样写稍微有点问题:

WebRequest request = WebRequest.Create(endpoint);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);
request.BeginGetResponse(new AsyncCallback(ResponseReady), request);

BeginGetResponse 不能注册这么早,我把它放在
void RequestReady(IAsyncResult asyncResult)
这个函数的末尾。

否则,如果你是在上传文件,会发现服务器端打开的文件流长度总为 0, 一打开就关闭了。



  回复  引用  查看    
#26楼 2008-07-27 17:53 | 木野狐(Neil Chen)      
Stream requestStream = request.EndGetRequestStream(asyncResult);

这个执行后 request 已经结束了,但实际要 post 的内容还没来得及发送,就执行到了获取 response 的环节。
  回复  引用    
#27楼 2008-07-30 11:27 | hp100277 [未注册用户]
按照25楼的修改
执行到
lblPrice.Text = "价格:" + reader.ReadToEnd();

报错:
Invalid cross-thread access

我用的是silverlight 2 beta 2版本

不知是怎么回事

  回复  引用  查看    
#28楼 2008-07-30 12:16 | 木野狐(Neil Chen)      
@hp100277
参考:
如何在 Worker thread 中更新 UI
http://www.cnblogs.com/RChen/archive/2008/07/25/1250948.html
  回复  引用    
#29楼 2008-08-23 09:41 | Lunardfsf [未注册用户]
我用的是silverlight 2 beta 2中文版本,没有报错,也没有提示,但是没实现功能,选择书籍时却没有出现对应的价格


  回复  引用  查看    
#30楼 [楼主]2008-08-25 11:30 | TerryLee      
@Lunardfsf
无非两个问题:
1.跨线程更新UI

2.跨域调用

根据这两点重新检查一下,看有没有这两个问题存在。
  回复  引用    
#31楼 2008-08-26 10:25 | xiaoguiyan [未注册用户]
很高兴看到您写的关于silverlight的文章。我现在用B2开发。有关WebRequest请求都不能用
Uri location = new Uri("http://www.cookies.test.cn/peopleData.xml"" target="_new" rel="nofollow">http://www.cookies.test.cn/peopleData.xml", UriKind.RelativeOrAbsolute);
WebRequest request = WebRequest.Create(location);
request.ContentType = "application/x-www-form-urlencoded";
request.BeginGetResponse(new AsyncCallback(this.OpenStreamCompleted), request);
}
void OpenStreamCompleted(IAsyncResult ar)
{

WebRequest request = ar.AsyncState as WebRequest;
WebResponse response = request.EndGetResponse(ar);
Stream responseStream = response.GetResponseStream();
using (StreamReader streamreader = new StreamReader(responseStream))
{
XDocument document = XDocument.Load(streamreader);
// Output the content of the document here.
var foundPeople = document.Descendants("person")
.Where(p => Convert.ToInt32(p.Element("age").Value) > 20)
.Select(p => new
{
Name = p.Element("firstname").Value + " "
+ p.Element("lastname").Value,
Age = Convert.ToInt32(p.Element("age").Value),
Phone = p.Elements("phone").Select(ph => ph.Value).ToArray(),
}
);
foreach (var person in foundPeople)
{
HtmlPage.Window.Alert(person.Phone[0].ToString());
}
}
}
http://www.cookies.test.cn/peopleData.xml 这地址是可以访问的,peopleData.xml权限也没问题可是报用户代码未处理 System.Net.ProtocolViolationException
错误。麻烦您指点一下。谢谢

  回复  引用  查看    
#32楼 [楼主]2008-08-27 09:48 | TerryLee      
@xiaoguiyan
可能是跨域调用的问题,你需要在www.cookies.test.cn下有一个域访问策略文件。
  回复  引用    
#33楼 2008-08-28 15:51 | xhz [未注册用户]
--引用--------------------------------------------------
木野狐(Neil Chen): 这样写稍微有点问题:

WebRequest request = WebRequest.Create(endpoint);
request.Method = &quot;POST&quot;;
request.ContentType = &quot;application/x-www-form-urlencoded&quot;;
request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);
request.BeginGetResponse(new AsyncCallback(ResponseReady), request);

BeginGetResponse 不能注册这么早,我把它放在
void RequestReady(IAsyncResult asyncResult)
这个函数的末尾。

否则,如果你是在上传文件,会发现服务器端打开的文件流长度总为 0, 一打开就关闭了。



--------------------------------------------------------
没看懂是怎么改的。

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
博客园首页

新闻频道

社区

小组

博问

网摘

闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-03-10 18:31 编辑过
成果网帮您增加网站收入


相关链接:

历史上的今天:
2006-03-09 重载还是覆写?