静观己心,厚积薄发

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::
Silverlight

Silverlight 应用程序常常需要访问后端服务器上的某些数据或功能。例如,如果您正在写入客户管理应用程序,该服务器可能包含您的 Silverlight 应用程序需要检索的客户数据库。如果您正在写入游戏,该服务器可能包含您的 Silverlight 应用程序需要更新的高分数信息。在很多情况下,让 Silverlight 能够使用服务器上的功能的最好方法是创建 Web 服务,如本主题所述。

本主题描述了如何将启用 Silverlight 的服务添加到现有的服务器端项目。一般情况下,这将是 Visual Studio 2010 包含在您的 Silverlight 解决方案中的默认 Web 应用程序。例如,如果正在构建名为 SilverlightApplication1 的应用程序,您将在“解决方案资源管理器”中看到名为 SilverlightApplication1.Web 的 Web 应用程序。但是您可以向任何其他网站或 Web 应用程序添加服务,甚至可以创建一个全新的 WCF 服务应用程序项目。

此过程假定您要在开发环境中使用 Visual Studio 2010。为方便起见,前面的几个步骤将描述在创建 Silverlight 解决方案时如何生成默认的 Web 应用程序。如果要使用另一个项目承载该服务,则可以跳过这几步操作。

有关概述如何通过 Silverlight 客户端访问在此主题中创建的服务的过程,请参见如何:从 Silverlight 访问服务

将启用 Silverlight 的 WCF 服务添加到现有网站或 Web 应用程序

  1. “文件”菜单中依次选择“新建”“项目”,然后从“项目类型”中选择 Silverlight,再从“安装了 Visual Studio 的模板”中选择“Silverlight 应用程序”。接受默认“名称”SilverlightApplicaton1,然后单击“确定”

  2. 在弹出的“新建 Silverlight 应用程序”向导中,接受已选中的默认选项“在新网站中承载 Silverlight 应用程序”。接受“新建 Web 项目名称”的默认值 SilverlightApplication1.Web,并接受默认的“ASP.NET Web 应用程序项目”作为“新建 Web 项目类型”。然后单击“确定”

  3. 若要将启用 Silverlight 的 Windows Communication Foundation (WCF) 服务添加到生成的默认 Web 应用程序中,请右击“解决方案资源管理器”中的 SilverlightApplication1.Web 项目,并选择“添加”,然后选择“新建项”打开“添加新项”窗口。在左侧的“已安装的模板”窗格中,从相关语言组(Visual C#Visual Basic)中选择“Silverlight”,然后从中央窗格中选择“启用了 Silverlight 的 WCF 服务”模板。在底部附近的“名称”框中将服务名称更改为 CustomerService.svc,然后单击该框右侧的“添加”按钮。

  4. 若要定义和实现 CustomerService 协定,请使用希望服务支持的操作替换 CustomerService 类中的 DoWork 方法(已在 CustomerService.svc.cs 文件中定义)。在此示例中,我们将添加两项操作以支持 Silverlight 客户端检索数据库中的用户数量以及每个用户的信息。

    [OperationContract]
    public int CountUsers()
    {
        return 2;
    }
    [OperationContract]
    public User GetUser(int id)
    {
      if (id == 1)
      {
      return new User() { IsMember = true, Name = "Paul", Age = 24};
      }
      else
      {
      return new User() { IsMember = false, Name = "John", Age = 64};
      }
    }
    
    
    

    不要忘记将 OperationContractAttribute 属性应用于每项操作。您所定义的服务基于 Windows Communication Foundation (WCF) 技术。本主题仅使用 WCF 的基本功能。有关更多信息,请参阅 WCF 文档,具体为设计和实现服务这一主题。

  5. 服务中使用的类型需要遵守称为数据协定的特定规则。创建有效类型的最简单方法是确保它是公用的,具有公共成员,并且具有不需要任何参数的公共构造函数。全部公开即隐式定义了此类型的数据协定。例如,可以按如下方式实现 GetUser 操作中的 User 类型(在 SilverlightApplication1.Web 命名空间中,CustomerService 类后面)。

    public class User
    {
    
        public bool IsMember { get; set; }
    
        public string Name { get; set; }
    
        public int Age { get; set; }
    }
    
    

    默认情况下,DataContractSerializer 序列化所有公开可见的类型,包括这些类型的所有公共的读/写属性和字段。因此,User 类的成员将是可序列化的。有关默认的序列化行为的信息,请参见可序列化类型

    您不需要应用 DataContractAttributeDataMemberAttribute 以选择使用序列化过程。有关服务中可以使用的类型的更多信息,请参见数据协定序列化程序支持的类型

  6. 若要在 Visual Studio 中测试服务实现,请选择“解决方案资源管理器”中的 CustomerService.svc 文件,然后右击并选择“在浏览器中查看”(或按 Ctrl + F5)以显示服务的测试页。您应看到“CustomerService 服务”测试页,这样便可确定该服务可用。

创建服务时的其他注意事项

对 Silverlight 可以访问的服务类型存在一些限制。如果不使用“启用 Silverlight 的 WCF 服务”模板创建 WCF 服务,则必须确保使用 BasicHttpBinding 配置 WCF 服务,以便支持该服务。同样支持 PollingDuplexHttpBinding。有关使用双工绑定的更多信息,请参见生成和访问双工服务。请注意,不能使用其他 WCF 绑定,因为 Silverlight 客户端不支持这些绑定所需的功能。例如,WSHttpBinding 所需的会话和事务即不受支持。有关访问 SOAP 服务(包括并非使用 WCF 甚至是并非使用 .NET Framework 创建的 SOAP 服务)时的 Silverlight 4 限制的更多信息,请参见访问 SOAP 服务

当在承载 Silverlight 应用程序的网站之外的任何位置创建服务时,都会产生跨域问题。在 Silverlight 应用程序和服务之间进行跨域调用时会出现安全漏洞,且必须由相应跨域策略明确启用该跨域调用。有关描述如何实现这类策略的过程,请参见使服务跨域边界可用

当在 Visual Studio 中调试多个单独的 Web 应用程序项目时,常常会出现这种情况,因为已向每个 Web 应用程序分配了不同的端口号。例如,您的 Silverlight 应用程序可能位于 http://localhost:1111 上,而您的服务可能位于 http://localhost:2222 上。即使计算机名相同 (localhost),端口号的不同也足以造成跨域问题,您必须按照使服务跨域边界可用中的描述进行处理。

当您使用“启用 Silverlight 的 WCF 服务”模板时,Web.config 文件会自动改为启用 ASP.NET 兼容模式,以便于将您的支持服务的 Silverlight 应用程序与 ASP.NET 安全模型相集成。这样您就可以完成很多工作,例如,可以限制仅通过身份验证的用户拥有对特定服务的访问权限,或者限制拥有特定角色的用户拥有访问权限。出现在相同项目中的所有 WCF 服务都必须使用 AspNetCompatibilityRequirements AspNetCompatibilityRequirements 特性配置为允许 ASP.NET 兼容模式。可以为使用“启用了 Silverlight 的 WCF 服务”模板添加的所有服务自动执行此操作,但您必须为可能在同一项目中具有的所有其他 WCF 服务手动完成此操作。此操作的备选操作是关闭 Web.config 中的 ASP.NET 兼容性模式(如果您的服务都不需要该模式)。

当使用服务访问数据库时,通过 ADO.NET Entity Framework 使用从数据库自动生成的类型很方便。这些生成的类型完全与专门供 Silverlight 使用的服务兼容。还经常便于在服务实现中使用 LINQ。例如,假定您的数据库具有 Users 表,且已从您的数据库生成 MyDatabaseEntities 实体模式,则可以按照以下方式实现用于按名称查找用户的操作。

[OperationContract]
public IEnumerable<User> GetUsersByName(string nameToSearch)
{
    MyDatabaseEntities e = new MyDatabaseEntities();
    return (from user in e.User where user.Name.Contains(nameToSearch) select user);
}

示例

以下示例总结了完成以上过程后 CustomerService.svc.cs 文件中的代码。

//CustomerService.svc.cs
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace SilverlightApplication1.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CustomerService
    {
        [OperationContract]
        public int CountUsers()
        {
            return 2;
        }
        [OperationContract]
        public User GetUser(int id)
        {
            if (id == 1)
            {
                return new User() { IsMember = true, Name = "Paul", Age = 24 };
            }
            else
            {
                return new User() { IsMember = false, Name = "John", Age = 64 };
            }
        }
    }

// All public read/write properties and fields of a type are serialized by default.

    public class User
    {

        public bool IsMember { get; set; }


        public string Name { get; set; }


        public int Age { get; set; }
    }

}

posted on 2011-02-15 10:32  猎人杰  阅读(446)  评论(0编辑  收藏  举报