前言: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>
{
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:
<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将不能访问那些资源。不过可以通过间接途径实现无策略文件跨域访问。下一篇介绍。