六、使用 Silverlight 处理 RESTful 数据

这是本书的倒数第二章,在这一章中,我们将探讨如何使用 Silverlight 5 使用 WCF 4.5 的 RIA 和 RESTful 服务。

在本章中,我们将涵盖以下几点:

  • Silverlight 5 简介
    • Silverlight 5 中的新特性
  • 理解 WCF 4.5 RIA 服务
  • 实现一个使用 WCF 4.5 RIA 服务的示例应用
  • 使用 Silverlight 5 客户端使用 WCF 4.5 RIA 服务

Silverlight 5 简介

Silverlight(代号为 Windows Presentation Foundation/Everywhere 或 WPF/E)是一个浏览器插件。 Silverlight 是一种提供 RIA 支持的客户端技术。 它可以用来增强基于 web 的应用的外观和感觉。 Silverlight 的新版本包含了构建基于 ria 的业务应用和富媒体应用的增强功能。 跨浏览器和跨平台的兼容性以及对富图形和动画的强大支持是 Silverlight 的一些显著特性。 而且,它运行在沙箱环境中——WPF 框架的一个子集。

Silverlight 的新版本提供了对打印(包括虚拟打印预览)、COM 自动化、Web cam 和麦克风、MEF(托管扩展框架)和 WCF 4.5 RIA 服务的强大支持。 另一方面,Silverlight 5 应用的性能在很大程度上得到了优化。

WCF 4.5 RIA Services 提供了一个框架,帮助您使用 WCF 4.5 连接。net 客户端对象和。net 服务器对象。 Silverlight 的新版本提供了对 WCF 4.5 RIA Services 的支持。 请注意,WCF 4.5 RIA Services(以前称为。net RIA 服务)以优化的。net 二进制格式或 ATOM、JSON 或 OData 格式向 Silverlight 应用公开数据。 WCF 4.5 RIA Services 简化了 RIA 应用的开发,即使用 Silverlight 5 等技术设计的应用。 RIA 服务为您提供了一个无需复制中间层组件的框架。

Silverlight 为开发下一代跨浏览器、跨平台的富互联网应用(ria)提供了极好的支持。 它有助于设计和开发 web 和移动应用的引人入胜的、交互式的用户体验。 然而,Silverlight 5 看起来像微软的 Silverlight 的最新版本,HTML 5 将是未来的选择。

选择 Silverlight 5 还是 HTML 5 取决于很多因素。 如果你正在创建一个Line of Business Application(LOB),你可以选择 Silverlight 5 并利用它的数据绑定特性。 相反,如果您需要需要图像、链接和文本框、动画和交互性的应用,HTML 5 是一个更好的选择。 然而,Silverlight 5 更适合于内部网应用,而不是基于 web 的应用。 另外,请注意,Silverlight 5 只支持 Windows phone。

Silverlight 5 的新特性

以下是 Silverlight 4 和 5 新增的新功能:

  • 控件的增强:在 Silverlight 5 中添加到控件的新特性包括:文本溢出、支持多点点击、提前输入文本搜索、合并DataContextChanged事件、文本跟踪、文本呈现、布局、清晰度等方面的改进。 在 Silverlight 5 中,当使用SaveFileDialog框时,你可以使用DefaultFileName属性设置默认文件名。 下面是如何使用它:

    SaveFileDialog fileDialog = new SaveFileDialog(); fileDialog.DefaultFileName = "Demo.txt"; fileDialog.ShowDialog();

  • 数据绑定的改进。

  • XAML changes: In the XAML stack, the features that have been added in Silverlight 5 include: XAML debugging, markup extensions, implicit data templates, binding in styles, and so on. Extensible Application Markup Language or XAML is an XML-based declarative markup language from Microsoft that enables you to design stunning user interfaces for your WPF or Silverlight applications. The XAML content is stored in an .xaml file, and you can use XAML to separate the user interface definition of your applications from the runtime logic by using code-behind files.

    注意事项

    注意,XAML 调试只在 Internet Explorer 9 及以上版本中工作。

  • Implicit data template is a great new feature that enables you to set a data type using the DataType property to the data template, instead of attaching the data template to every control in your page. Here's an example of a code snippet that illustrates this:

    <ListBox x:Name="users"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding FirstName}" FontWeight="Bold" /> <TextBlock Text="{Binding LastName}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

    标记扩展是一种允许您在 XAML 解析时执行代码的特性。 其中包括{Binding}{StaticResource}{RelativeSource}等等。 您还可以创建自己的自定义标记扩展。

  • 更新/更改用户界面,图形和媒体。

  • 对网络摄像头和麦克风的支持:Silverlight 4 和 Silverlight 5 使您能够构建具有共享视频和音频能力的应用。
  • 优化的性能:使用 Silverlight 4 和 Silverlight 5 构建的应用与早期版本的 Silverlight 相比速度快得惊人。 此外,Silverlight 5 应用启动得更快。 Silverlight 5 支持 64 位操作系统,允许受信任的应用不受任何限制地访问本地文件系统。
  • 增强对 COM 互操作性的支持:Silverlight 4 和 Silverlight 5 可以与 COM 接口进行互操作。 下面的代码片段展示了如何从 Silverlight 与 Microsoft Office 应用通信:
  • 要让你的 Silverlight 4 和 Silverlight 5 应用与 Microsoft Word 进行通信,你可以编写以下代码:
  • 改进了对 RIA 服务的支持:在 Silverlight 5 中,对 WCF 4.5 RIA 服务的支持得到了改进。 现在您已经支持复杂类型、更好的 MVVM 支持,还支持对生成的代码进行更好的自定义。
  • 增强对浏览器外应用的支持:Silverlight 4 和 Silverlight 5 提供了对 RIA 应用的支持,而且这种支持无需下载和安装任何额外的代码或运行时。 现在您已经支持跨域网络访问、访问用户文件夹、COM Interop 和 HTML 托管。
  • 请注意,在ApplicationManifest.xaml文件中包含以下配置,以便在安装和使用浏览器外应用时可以利用提高的权限。

    <OutOfBrowserSettings.SecuritySettings> <SecuritySettings ElevatedPermissions="Required" /> </OutOfBrowserSettings.SecuritySettings>

WCF 4.5 RIA 服务

注意,在以数据为中心的系统中,即严重依赖数据的系统中,数据可能来自不同的系统。 现在,您的应用需要将业务逻辑对象和其他服务器对象驻留在客户端,以便能够访问数据。

这种方法的主要问题是代码的重复,以及客户端对内存资源的高消耗。 这就是 WCF 4.5 RIA Services 可以发挥作用的地方。 顺便提一下,WCF 4.5 RIA 服务是在。net Framework 4 和 Silverlight 4 中引入的。 它允许开发人员设计和实现应用,而不需要服务管道代码。

下图展示了一个典型的 WCF 4.5 RIA Services 应用的架构组件:

WCF 4.5 RIA Services

WCF 4.5 RIA Services(构建在 WCF 4.5 服务之上)简化了 n 层应用开发(尤其是使用 Silverlight 的应用),而无需编写服务管道代码。 实际上,如果您使用 WCF 4.5 RIA Services,您的应用逻辑可以驻留在服务器上。 客户端无需在客户端(即服务使用者端)复制应用的逻辑组件就可以使用这一功能。 RIA 服务构建在 WCF 4.5 之上,简化了客户端编程模型。 然而,RIA 服务也有一些潜在的缺点。 最重要的是,处理元数据是一件痛苦的事情,特别是当您需要经常更新您的模型时。 如果您有一个包含许多实体的数据库,那么当您使用 RIA 服务时,您将花费更多的时间来更新您的模型。

注意事项

如果你使用 WCF 4.5 RIA Services,服务消费者可以在服务器端的业务逻辑组件发生变化时获得最新的更新。

下面是 WCF 4.5 RIA Services 提供的一些特性:

  • 当您使用 WCF 4.5 RIA Services 时,客户端实例是通过依赖于服务器端对象的反射来创建的,而不是由服务器上执行的服务公开的服务契约。
  • WCF 4.5 RIA 服务提供了对 LINQ 查询序列化的支持; 所以,你可以在客户端编写 LINQ 查询,并在服务器端执行它。

实现示例应用

在本节中,我们将实现一个样例应用,演示如何设计和实现一个 WCF 4.5 RIA 服务,然后使用 Silverlight 5 使用它。 当你创建一个 Silverlight 应用时,你可以选中启用 WCF RIA Services复选框。 这将确保创建 RIA 服务链接,当您最终构建完整的解决方案时,将为域服务和共享代码生成客户端代码。

要开始在 Silverlight 5 中使用 WCF 4.5 RIA Services,请遵循以下简单步骤:

  1. 打开 Visual Studio 2013 IDE。
  2. 点击文件,再点击新建项目
  3. Select Silverlight from the templates displayed, and save it with a Name:, as shown in the following screenshot:

    Implementing a sample application

  4. 接下来,删除Solution Explorer窗口中的服务器和客户端项目中的Class1.cs文件。

  5. After you delete the Class1.cs file in both the Server and Client projects, the Solution Explorer window would look like this:

    Implementing a sample application

  6. Next, right-click on References in the Demo.Web project, and select Manage NuGet Packages... from the menu that is displayed, as shown in the following screenshot:

    Implementing a sample application

  7. From the list of packages Online | All, you can see EntityFramework listed on the next page. Click on Install, as shown in the following screenshot:

    Implementing a sample application

    当你点击安装,实体框架的安装将开始。

    注意事项

    请注意,您也可以通过在包管理器控制台中执行命令来安装实体框架。 您可以在 NuGet 网站http://www.nuget.org/packages/entityframework了解更多关于实体框架版本的详细信息。

    实体框架安装成功后,您可以看到如下截图所示的绿色标记:

    Implementing a sample application

  8. Next, create a solution folder named Models, and a new entity data model using the AdventureWorks database.

    Implementing a sample application

  9. 接下来,在您的 web 项目中创建两个文件夹,一个名为App-Code,另一个名为Services

  10. Now, create a DomainService class. To do this, navigate to Add | New Item on the Services solution folder, and select Web from the list of the installed templates. Then select Domain Service Class. Name this class DepartmentDomainService.cs and, click on Add.

    注意事项

    如果你想在 WCF 4.5 RIA Services 中利用实体框架实体数据模型,你应该将其转换为基于“ObjectContext”的模型,否则你在创建域服务时将看不到列出的实体。 您将观察到这样一条消息:一些实体框架上下文类可能已经被排除

    要解决此问题,请在设计器模式中打开实体数据模型,并将代码生成策略更改为默认。 接下来,删除与模型相邻的两个.tt文件,然后重新构建项目。

  11. The next step is to add a domain service class. Refer to the following screenshot:

    Implementing a sample application

  12. 当您点击OK时,框架将自动创建Department实体的域服务类。

注意事项

需要注意的是,如果你将一个类库项目添加到一个 Silverlight 业务应用项目中,你将不能向服务器项目添加身份验证服务。 这是因为 Silverlight 业务应用模板中的用户对象不能从类库项目中访问。

需要注意的是,Silverlight 无法与服务器端共享程序集。 为了弥补这个差距,我们使用了。net RIA Services。 如果使用。net RIA Services,则在客户端生成的代码几乎是域类的副本。 这确保了您可以在服务器端和客户端之间来回移动对象。 下图说明了RIA 链接Silverlight 应用之间建立【显示】的 Web 应用,当您使用 WCF RIA 服务使用 Silverlight 和使用它们:

Implementing a sample application

现在让我们看一下自动生成的Domain Service类。 下面是DepartmentDomainService类的样子:

namespace Demo.Web.Services
{
    using System.Data;
    using System.Linq;
    using System.ServiceModel.DomainServices.EntityFramework;
    using System.ServiceModel.DomainServices.Hosting;
    using Demo.Web.Models;

    [EnableClientAccess()]
    public class DepartmentDomainService : LinqToEntitiesDomainService<AdventureWorks2008R2Entities>
    {
        public IQueryable<Department> GetDepartments()
        {
            return this.ObjectContext.Departments;
        }

        public void InsertDepartment(Department department)
        {
            if ((department.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(department, EntityState.Added);
            }
            else
            {
                this.ObjectContext.Departments.AddObject(department);
            }
        }

        public void UpdateDepartment(Department currentDepartment)
        {
            this.ObjectContext.Departments.AttachAsModified(currentDepartment, this.ChangeSet.GetOriginal(currentDepartment));
        }

        public void DeleteDepartment(Department department)
        {
            if ((department.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(department, EntityState.Deleted);
            }
            else
            {
                this.ObjectContext.Departments.Attach(department);
                this.ObjectContext.Departments.DeleteObject(department);
            }
        }
    }
}

请参考前面的代码片段。 在构建 LOB 应用时,常见的特性是对数据进行创建、更新、读取和删除操作。 System.Web.Ria名称空间中的EnableClientAccessAttribute属性允许在编译时生成客户端代码。

现在,您可以指定必要的配置来使用这个 WCF 4.5 RIA 服务公开的数据。

现在,让我们基于本书前面创建的SecurityDB快速创建一个域服务类。

遵循以下步骤:

  1. 创建一个名为DomainServices的新项目。
  2. Create an entity data model based on the Control and ControlType tables of SecurityDB as shown in the following screenshot:

    Implementing a sample application

  3. 选择新创建的项目,然后右键单击并导航到Add|New Item

  4. Select Domain Service Class from the templates displayed as shown in the following screenshot:

    Implementing a sample application

  5. Now, name the Domain Service Class as SecurityDomainService.cs and click on Add. You will see a page that looks like the following screenshot:

    Implementing a sample application

如您所见,列出了两个实体ControlControlType。 选择两者,然后点击OK。 现在将生成域服务类。 乍一看,SecurityDomainService类是这样的:

namespace DomainServices
{
    using System.Linq;
    using System.ServiceModel.DomainServices.EntityFramework;
    using System.ServiceModel.DomainServices.Hosting;
    [EnableClientAccess()]
    public class SecurityDomainService : LinqToEntitiesDomainService<SecurityDBEntities>
    {
        public IQueryable<Control> GetControls()
        {
            return this.ObjectContext.Controls;
        }

        public IQueryable<ControlType> GetControlTypes()
        {
            return this.ObjectContext.ControlTypes;
        }
    }
}

CRUD 操作

下一步是将必要的 CRUD 方法添加到 Domain Service 中,用于创建新记录、更新现有记录、删除现有记录以及检索属于ControlControlType表的一个或多个记录。

以下是SecurityDomainService类添加了必要的 CRUD 方法后的完整代码:

namespace DomainServices
{
    using System.Data;
    using System.Linq;
    using System.ServiceModel.DomainServices.EntityFramework;
    using System.ServiceModel.DomainServices.Hosting;

    [EnableClientAccess()]
    public class SecurityDomainService : LinqToEntitiesDomainService<SecurityDBEntities>
    {
        public IQueryable<Control> GetControls()
        {
            return this.ObjectContext.Controls;
        }

        public IQueryable<ControlType> GetControlTypes()
        {
            return this.ObjectContext.ControlTypes;
        }

        public IQueryable<Control> GetControls()
        {
            return this.ObjectContext.Controls;
        }

        public IQueryable<ControlType> GetControlTypes()
        {
            return this.ObjectContext.ControlTypes;
        }

        public void InsertControl(Control control)
        {
            if ((control.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(control, EntityState.Added);
            }
            else
            {
                this.ObjectContext.Controls.AddObject(control);
            }
        }

        public void InsertControlType(ControlType controlType)
        {
            if ((controlType.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(controlType, EntityState.Added);
            }
            else
            {
                this.ObjectContext.ControlTypes.AddObject(controlType);
            }
        }

        public void UpdateControls(Control controlObj)
        {
            this.ObjectContext.Controls.AttachAsModified(controlObj, this.ChangeSet.GetOriginal(controlObj));
        }

        public void UpdateControlTypes(ControlType controlTypeObj)
        {
            this.ObjectContext.ControlTypes.AttachAsModified(controlTypeObj, this.ChangeSet.GetOriginal(controlTypeObj));
        }

        public void DeleteControls(Control controlObj)
        {
            if ((controlObj.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(controlObj, EntityState.Deleted);
            }
            else
            {
                this.ObjectContext.Controls.Attach(controlObj);
                this.ObjectContext.Controls.DeleteObject(controlObj);
            }
        }

        public void DeleteControlTypes(ControlType controlTypeObj)
        {
            if ((controlTypeObj.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(controlTypeObj, EntityState.Deleted);
            }
            else
            {
                this.ObjectContext.ControlTypes.Attach(controlTypeObj);
                this.ObjectContext.ControlTypes.DeleteObject(controlTypeObj);
            }
        }
    }
}

要使用 Silverlight 5 中的域服务,您需要遵循本章前面讨论的相同步骤。

注意事项

这里有一些链接,以进一步参考这个主题:

总结

您可以使用 WCF 4.5 RIA Services 编写从小型业务应用到非常复杂的应用的应用。 在本章中,我们已经讨论了 WCF 4.5 RIA 服务,以及如何在 Silverlight 5 应用中使用它们。 在下一章中,我们将讨论一些高级特性,包括使用 WCF 服务和 ASP 的最佳实践。 净 Web API。