飘遥的Blog

C/C++/.NET
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

乱弹琴 Silverlight 2.0 (21) 网络访问及数据通信(一)

Posted on 2008-05-13 04:52  Zzx飘遥  阅读(310)  评论(1编辑  收藏  举报

前言:Silverlight 2.0 Beta1 已经发布,加入了许多激动人心的新特性:WPF UI 框架、丰富的控件、丰富的网络支持、丰富的基础类库支持等。这是本人的学习笔记,写的比较乱,因此定名为乱弹琴Silverlight 2.0 系列文章。
 
本篇用一个示例(RSS订阅)介绍WebClient类和跨域访问的相关信息。

Silverlight 2.0的System.Net命名空间为网络及数据通信提供了很好的支持。
本片介绍的 WebClient 类暂时只支持异步访问。

示例(RSS订阅)

XAML:
<Grid x:Name="LayoutRoot" Background="DarkGreen" ShowGridLines="True">
    
<Grid.ColumnDefinitions>
        
<ColumnDefinition Width="*"></ColumnDefinition>
    
</Grid.ColumnDefinitions>
    
<Grid.RowDefinitions>
        
<RowDefinition Height="50"></RowDefinition>
        
<RowDefinition Height="25"></RowDefinition>
        
<RowDefinition Height="25"></RowDefinition>
        
<RowDefinition Height="*"></RowDefinition>            
    
</Grid.RowDefinitions>
    
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
        
<WatermarkedTextBox x:Name="txtUrl" Grid.Row="0"
                            Text
="http://www.xianfen.net/RSS0.aspx"
                            Watermark
="请输入RSS地址" Height="30" Width="240">                
        
</WatermarkedTextBox>
        
<Button Width="60" Height="30" Content="GetRSS" Click="Button_Click"></Button>
    
</StackPanel>
    
<TextBlock x:Name="txtTitle" Foreground="Yellow" FontSize="16" Grid.Row="1"></TextBlock>
    
<HyperlinkButton x:Name="hlkLink" Foreground="Yellow" FontSize="16" Grid.Row="2">            
    
</HyperlinkButton>
    
<ListBox x:Name="lstRSS" Height="500" Grid.Row="3" SelectionChanged="lstRSS_SelectionChanged">
        
<ListBox.ItemTemplate>
            
<DataTemplate>
                
<TextBlock Text="{Binding Title }" Width="260"
                           TextWrapping
="Wrap" Foreground="DarkGreen">                        
                
</TextBlock>
            
</DataTemplate>
        
</ListBox.ItemTemplate>
    
</ListBox>
</Grid>

C#:
public partial class Page : UserControl
{
    
public Page()
    {
        InitializeComponent();
    }

    
private void Button_Click(object sender, RoutedEventArgs e)
    {
        WebClient webClient
= new WebClient();

        
try
        {
            webClient.DownloadStringAsync(
new Uri(txtUrl.Text));
        }
        
catch
        {
            txtUrl.Text
= "请输入合法的RSS地址!";
            
return;
        }

        webClient.DownloadStringCompleted
+=
            
new DownloadStringCompletedEventHandler(
                webClient_DownloadStringCompleted);
    }

    
void webClient_DownloadStringCompleted(object sender,
        DownloadStringCompletedEventArgs e)
    {
        
try
        {
            List
<RSSItem> rssList = new List<RSSItem>();
            
byte[] bytes = Encoding.UTF8.GetBytes(e.Result);
            Stream stream
= new MemoryStream(bytes);
            XmlReader xmlReader
= XmlReader.Create(stream);

            xmlReader.MoveToContent();

            
if (xmlReader.ReadToFollowing("title"))
            {
                txtTitle.Text
= xmlReader.ReadElementContentAsString();
            }

            
if (xmlReader.ReadToFollowing("link"))
            {
                hlkLink.TargetName
= "_blank";
                hlkLink.Content
= xmlReader.ReadElementContentAsString();
                hlkLink.NavigateUri
= new Uri(hlkLink.Content.ToString(),
                    UriKind.Absolute);
            }

            
if (xmlReader.ReadToFollowing("item"))
            {
                RSSItem rss
= new RSSItem();

                
while (xmlReader.Read())
                {
                    
if (xmlReader.IsStartElement("title"))
                    {
                        rss.Title
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("link"))
                    {
                        rss.Link
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("category"))
                    {
                        rss.Category
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("author"))
                    {
                        rss.Author
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("pubDate"))
                    {
                        rss.PubDate
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("guid"))
                    {
                        rss.Guid
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("description"))
                    {
                        rss.Description
= xmlReader.ReadElementContentAsString();
                    }
                    
else if (xmlReader.IsStartElement("item"))
                    {
                        rssList.Add(rss);
                        rss
= new RSSItem();
                    }
                }

                rssList.Add(rss);
            }

            lstRSS.ItemsSource
= rssList;
        }
        
catch (Exception ex)
        {
            HtmlPage.Window.Alert(
"出现异常:\n" + ex.Message);
        }
    }

    
private void lstRSS_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        RSSItem rss
= lstRSS.SelectedItem as RSSItem;

        
if (rss != null)
        {
            HtmlPage.Window.Invoke(
"setContent", rss.Title, rss.Link,
                rss.PubDate, rss.Category, rss.Description);
        }
    }
}

//RSS Item
public class RSSItem
{
    
public string Title { get; set; }
    
public string Link { get; set; }
    
public string Category { get; set; }
    
public string Author { get; set; }
    
public string PubDate { get; set; }
    
public string Guid { get; set; }
    
public string Description { get; set; } 
}

HTML:
<div style="float: left;">
    
<asp:Silverlight ID="Xaml1" runat="server"
    Source
="~/ClientBin/TestNet.xap" Version="2.0"
        Width
="300px" Height="600px" Windowless="True" />
</div>
<div id="content" style="float: left; width: 400px;">
    
<div id="title">
        
<a id="anchor" target="_blank"></a>
    
</div>
    
<div id="pubDate">
    
</div>
    
<div id="category">
    
</div>
    
<div id="description">
    
</div>
</div>
</form>

<script type="text/javascript">
function setContent(title, link, pubDate, category, description)
{
    document.getElementById(
"anchor").href = link;
    document.getElementById(
"anchor").innerHTML = title;
    document.getElementById(
"pubDate").innerHTML = pubDate;
    document.getElementById(
"category").innerHTML = category;
    document.getElementById(
"description").innerHTML = description;
}
</script>


运行效果:



跨域访问

输入有的RSS地址会出现一下错误:


这是由于Silverlight出于安全的原因,禁止跨域访问,可以在要访问的URI特定目录(可配置)放如跨域策略文件,Silverlight的策略文件跟falsh跨域策略文件兼容。内容为:
crossdomain.xml:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  
<allow-access-from domain="xianfen.net" />
</cross-domain-policy>

或:
clientaccesspolicy.xml:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  
<cross-domain-access>
    
<policy>
      
<allow-from>
        
<domain uri="*"/>
      
</allow-from>
      
<grant-to>
        
<resource path="/" include-subpaths="true"/>
      
</grant-to>
    
</policy>
  
</cross-domain-access>
</access-policy>

结束语

跨域策略文件能保证安全性并且控制访问,如果没有权限放置跨域策略文件,Silverlight将不能访问那些资源。不过可以通过间接途径实现无策略文件跨域访问。下一篇介绍。