65.9K
CodeProject 正在变化。 阅读更多。
Home

MyFeedReader - 一个简单的 Feed 阅读器,使用 ASP.NET 3.5、LINQ、WCF Syndication API 和 AJAX

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (29投票s)

2007年12月27日

CPOL

7分钟阅读

viewsIcon

60791

downloadIcon

460

一篇关于使用 .NET 3.5 和 Visual Studio 2008 引入的新技术创建快速强大的应用程序的文章

引言

有这么多令人兴奋的新技术和功能刚刚发布或即将发布:Visual Studio 2008、LINQ、MVC Framework、Entity Framework、AJAX、WCF,仅举几例。这是个好消息,但也有代价。需要阅读、学习和跟进的内容更多;但我相信这是值得的。

写这篇文章时遇到的第一个问题是“写什么?”经过几个小时的思考,我决定写一个小应用程序,涵盖这些主题中的许多,然后简洁地讨论每个主题。所以,不要期望对所有这些主题进行深入的分析。相反,我将向您展示这些技术组合在一起的力量。

对于我的示例应用程序,我将创建一个简单的基于 Web 的 feed/RSS 阅读器。在此应用程序中,我将探讨以下技术:

  1. ListView – ASP.NET 3.5 的新 Web 控件
  2. LINQ
  3. Syndication API – Windows Communication Foundation (WCF) 的一部分
  4. AJAX 和 AJAX Toolkit

我将在文章中指出 Visual Studio 2008 的一些新功能。

开始

让我们开始创建一个新的网站

Screenshot - image002.jpg

Screenshot - image004.jpg

这将自动创建一个完全支持 Microsoft AJAX 的网站 - 但不支持 AJAX Toolkit。要使用 AJAX Toolkit,您需要下载并安装针对 3.5 .NET Framework 的版本。

现在,让我们创建 UI。用户界面中的主要组件是树视图和列表视图。树视图将包含您所有的 feed,列表视图将显示所选 feed 的 feed 项。.

Screenshot - image006.jpg

Syndication API

如果没有添加 feed,feed 阅读器就没有用。所以,我们需要做的第一件事是添加 feed。页面顶部有一个文本框和一个添加按钮。您只需键入 feed URL 并单击添加按钮。这就是新的强大的 Syndication API 发挥作用的地方。您不必解析 XML、进行 HTTP 调用并编写混乱的代码。您所要做的就是写两行代码。是的,这不是错别字,是两行代码。

Dim xmlReader = System.Xml.XmlReader.Create(feedUrl)
 Dim feed = SyndicationFeed.Load(xmlReader)

第一行使用用户提供的 feed URL 创建一个 XML 读取器。第二行检索 feed 和 feed 项。记住导入 System.ServiceModel.Syndication 命名空间以轻松使用 syndication API。这就是我们要做的全部。现在我们有了一个强类型 feed,类型为 SyndicationFeed,包含一个 SyndicationItem 的集合。让我们显示它。

用户界面和 ListView

当用户从树视图中选择一个 feed 时,我们需要在列表视图中显示 feed 项。当然,您可以使用任何您想要的 data control,如 DataList 或 Repeater。但既然我们在探索新事物,就让我们使用 ListView 控件。渲染 ListView 需要采取两个重要的步骤:

  1. 添加 LayoutTemplate
  2. 添加 ItemTemplate

LayoutTemplate 必须包含一个名为“itemPlaceholder”的元素,该元素具有 runat=”server” 属性。这 - 顾名思义 - 充当占位符。

<LayoutTemplate>
 <table runat="server" id="table1" runat="server">
     <tr runat="server" id="itemPlaceholder"> </tr>
 </table> 
</LayoutTemplate> 

ItemTemplate 应包含一个与布局模板中定义的 itemPlaceholder 相同类型的元素。在这种情况下,占位符是 TR 元素。

<ItemTemplate>
   <tr runat="server">
       <td id="Td1" runat="server">
          <asp:Panel ID="lblTitle" runat="server" BackColor="#000066"
             ForeColor="white" Width="100%">
                 <%#Eval("Title.Text") %>
             [<a href='<%#Eval("Links(0).Uri.AbsoluteUri") %>'
                 target="_blank">link</a>]</asp:Panel>
          <asp:Panel ID="pnlContent" runat="server">
             <asp:Label ID="lblContent" runat="server"
                 Text='<%#Eval("Summary.Text") %>' /></asp:Panel>
       </td>
    </tr> 
</ItemTemplate>

ListView 将基本上用 ItemTemplate 中的代码替换 LayoutTemplate 中的 itemPlaceholder 项。您可以在 DataList 或 Repeater 中做同样的事情,但 ListView 控件可以让你在不写代码的情况下编辑、插入、删除、排序、分页和分组数据。我强烈建议深入了解这个新的强大控件。

现在所有 UI 元素都已到位,让我们显示信息。我们只需遍历 SyndicationFeeds 列表并将每个 feed 标题添加到树节点列表中。当用户单击一个节点时,我们就获取该 feed 的项并将其绑定到 ListView。

Private Sub BindListView(ByVal feed As SyndicationFeed)
    Me.ListView1.DataSource = feed.Items
    Me.ListView1.DataBind()
End Sub

AJAX

为了使网页更易用,我将整个页面包装在一个 AJAX UpdatePanel 中,并将其与一个 UpdateProgress 面板关联起来。

<asp:UpdateProgress ID="UpdateProgress2" runat="server" 
    AssociatedUpdatePanelID="UpdatePanel2"
    DisplayAfter="0" DynamicLayout="True">
    <ProgressTemplate>
        <div class="progresspanel">
            Loading…
        </div>
    </ProgressTemplate>
</asp:UpdateProgress>

我为进度面板应用了一个漂亮的样式,使其与 Gmail 的“正在加载”消息具有相同的外观和感觉。它是一个红色矩形,在页面右上角显示白色的“正在加载...”字样。

.progresspanel
{
    background-color: RED;
    color: White;
    top: 1px;
    color: white;
    position: absolute;
    right: 16px;
    z-index: 999;
}

我还想让 ListView 中的项在单击 feed 标题时展开/折叠。为此,我使用了 AJAX Toolkit 中的 CollapsiblePanelExtender。由于 ListView 中的项是动态生成的,我不得不在代码中创建 Extender。我在 ListView 的 ItemCreated 事件中这样做了。我将项内容面板分配给 Extender 的 TargetControlID 属性,并将标题面板分配给 ExpandControlIDCollapseControlID 属性。我还将所有项设置为默认折叠状态。

Protected Sub ListView1_ItemCreated(ByVal sender As Object,
    ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles 
    ListView1.ItemCreated
    If e.Item.ItemType = ListViewItemType.DataItem Then
        Dim lblTitle As WebControl = e.Item.FindControl("lblTitle")
        Dim pnlContent As WebControl = e.Item.FindControl("pnlContent")
        Dim cpx As New AjaxControlToolkit.CollapsiblePanelExtender()
        cpx.ID = "cpx"
        cpx.TargetControlID = pnlContent.UniqueID
        cpx.CollapseControlID = lblTitle.UniqueID
        cpx.ExpandControlID = lblTitle.UniqueID
        cpx.Collapsed = True
        e.Item.Controls.Add(cpx)
    End If
End Sub

为了使第一个项展开,我向 ListView 的 PreRender 事件添加了一个事件处理程序。

Protected Sub ListView1_PreRender(ByVal sender As Object,
    ByVal e As System.EventArgs) Handles ListView1.PreRender
    If ListView1.Items.Count > 0 Then
        Dim cpx As AjaxControlToolkit.CollapsiblePanelExtender = 
             ListView1.Items(0).FindControl("cpx")
        If Not IsNothing(cpx) Then cpx.Collapsed = False
    End If
End Sub

我还使用了几个 TextWatermarkExtender 在文本框上显示水印。

LINQ

我喜欢新框架和 Visual Studio 的很多地方,但如果我必须选择一个我非常兴奋的功能/技术,那将是 LINQ – Language Integrated Query。这是一个相当大的主题,我在这里几乎只是触及了表面。

我想让用户搜索 feed 项标题中是否包含特定文本。没有 LINQ,我将不得不遍历这些项并搜索标题。但现在有了 LINQ,我就可以写一个简单的查询,对于任何写过 SQL 语句的人来说,它看起来都非常熟悉。

Dim matches = From item In CurrentFeed.Items _
              Where item.Title.Text.ToUpper _
              Like String.Format("*{0}*", txtFilter.Text.ToUpper)

上面的语句,我只是对 feed 项运行了一个“select”语句,并有一个条件,即只返回标题包含过滤/搜索文本的项。正如你所看到的,这看起来非常像 SQL,但它远不止于此。首先,返回的结果是强类型的,正如你在下面的工具提示中所看到的。

Screenshot - image008.jpg

其次,你真的无法在这里犯语法错误,因为编译器不会让你犯。与 SQL 相比,在 SQL 中,直到编译并运行应用程序,你才发现 SQL 语句有问题。第三,在你输入查询时,你会在 IDE 中获得完整的 IntelliSense 支持 - 看看下面的截图系列。

Screenshot - image010.jpg

Screenshot - image012.jpg

荣誉提名

上面的 LINQ 查询中有几点值得一提,这些是框架中的新内容。

隐式类型

正如你在 IntelliSense 中看到的,“matches”是根据查询结果强类型化的。这相当于:

            Dim matches As IEnumerable(Of SyndicationItem)

请记住,隐式类型与 Dim x as object 不同。这些是强类型对象,但它们不是明确声明为特定类型,而是由编译器和 IDE 根据赋值来推断类型。

例如,这两个语句是相同的:

Screenshot - image014.jpg

并且

Screenshot - image016.jpg

但这些不等于

Screenshot - image018.jpg

扩展方法

LINQ 之所以成为可能,完全是扩展方法的功劳。扩展方法只是一个向类“注入”静态/共享方法而不继承它的方法。举个例子,如果我们想在 IEnumerable(Of SyndicationItem) 类中编写上面的查询作为一个 Search 方法,并且我们想轻松地做到。首先要做的是创建扩展方法:

<Extension()> _
Function Search(ByVal Items As IEnumerable(Of SyndicationItem), _
                ByVal SearchTerm As String) As IEnumerable(Of SyndicationItem)
    Return From item In Items _
           Where item.Title.Text.ToUpper _
           Like String.Format("*{0}*", SearchTerm.ToUpper)
End Function

创建扩展方法的步骤是:

  1. 创建模块
  2. 创建方法并为其添加 <Extension> 属性 - 确保导入 System.Runtime.CompilerServices 命名空间
  3. 方法的第一个参数必须是你想要扩展的类

要使用扩展方法,只需像调用对象上的任何其他方法一样调用它:

Screenshot - image020.jpg

如果这都不算牛,那我真不知道什么算牛了!!!

结论

虽然我没有深入研究任何特定的技术或功能,但我想展示使用 .NET 3.5 框架和 Visual Studio 2008,只需很少的代码就可以快速轻松地创建有趣的应用程序。我们涵盖了 WCF 的 syndication API、ListView Web 控件、AJAX、AJAX Toolkit、LINQ、扩展方法和隐式类型。

您有什么看法?

我想听听您对这些新技术和本文的看法。我希望您觉得它有点用。请通过评论、电子邮件或访问我的网站 www.emadibrahim.com 告诉我您的想法:www.emadibrahim.com

© . All rights reserved.