数据点

在 Silverlight 3 中的数据性能和容错策略

John Papa

MSDN 代码库 中可用的代码下载
浏览在线代码

本文基于 Silverlight 3 的预发布版本。

内容

生成速度
二进制编码的配置
与文本数据的二进制数据
閿欒  娑堟伅是数据
解决问题
声明的错误
声明的错误
上的换行

Silverlight 应用程序通常依赖于其数据的 Web 服务。 数据检索,并能够检索有关 Web 服务中可能发生的异常有意义的信息的性能是改进了 Silverlight 3 中的两个关键区域。

性能不佳的原因可以是一个应用程序终止程序。 从 Web 服务中检索数据的好策略可以帮助,但有时需要检索对象图可以巨大和需要从 Web 服务传递到客户端很长时间。 Silverlight 3 提供了从使用二进制编码的 Web 服务传递数据的新功能,并传递大对象关系图时这可以显著提高性能。

服务与 Silverlight 应用程序之间传递数据时,可以转错误很多。 这就是一定要有一个好的策略处理调用 Web 服务时可能发生的异常的原因。 Silverlight 3 提供了一些网络增强功能,使开发人员将从 Web 服务传递的托管异常有关的信息更多选项。

在本月的列中我将演示如何将二进制编码工作,它的作用在应用程序的性能,和它的行为由演示它在操作中。 我还将介绍几种技术可用于通过使用声明和声明错误与 Windows 通信基础 (WCF) Web 服务将 Silverlight 的异常信息。 将首先演示时,发生异常并如何添加一些快速更改配置以显示在调试过程的信息将会发生。 然后,我将向您展示如何设置战略错误模式处理异常传递了通过使用 SOAP 服务的信息声明错误。 所有代码基于 Silverlight 3 测试版,并且联机本文附带。

生成速度

SOAP 和 XML 严重以文本形式传递 bloats WCF Silverlight 之间传递消息。 这可以造成负面影响在两个处理数据和通过 HTTP 传递数据所需的时间的性能。 Silverlight 3 引入了能够与 Silverlight 3 客户端应用程序进行通信的 WCF 服务中使用一个二进制消息编码器。 二进制消息编码器可以提高 WCF 的服务的性能,尤其是当传递大对象关系图。 在使用二进制消息编码的性能,最大收益实现传递数组、 数字,和对象图形时 ; 很小的邮件和字符串发现较少的收益。

这不是一个压缩的策略,所以装箱和解压缩压缩的数据的性能没有负面影响。 但是,二进制编码通常不会减小数据传递。 减小大小不保证,但使用大型对象关系图和整数数据时是显而易见的。 从二进制编码获得密钥改进是它进行优化以提高服务器的吞吐量。

二进制编码的配置

WCF 服务可以与 Silverlight 2 应用程序使用 basicHttpBinding,以文本形式发送数据,通过 HTTP 通信。 时使用的 Silverlight WCF 服务文件模板 — 瀹夎  Visual Studio Silverlight 工具时,该安装,若要创建 WCF 服务的 Silverlight 2,绑定被配置为使用 basicHttpBinding。 在 Silverlight 3 将 WCF 服务配置为使用二进制消息编码器而不是文本中更改了此文件的模板。

已启用 Silverlight 的 WCF 服务文件模板配置 WCF 服务使用二进制编码消息。 如果您使用现有的 WCF 服务,它可以将配置为使用二进制编码的 Web.config 文件中的绑定部分中创建自定义绑定的消息。 下面的代码示例显示名为 silverlightCustomBinding,它将显示在配置文件的 <system.serviceModel> 部分在自定义绑定。 配置为使用 binaryMessageEncoding 的该 silverlightCustomBinding 然后服务的终结点配置中其名称的引用。

<endpoint address="" binding="silverlightCustomBinding"
  contract="MyTestService" />
<bindings>
  <customBinding>
    <binding name="silverlightBinaryBinding">
      <binaryMessageEncoding />
      <httpTransport />
    </binding>
  </customBinding>
</bindings>

basicHttpBinding 通过 HTTP,作为文本发送消息,因为它很容易调试工具 (如 Fiddler 通过邮件。 而可以仍将配置 basicHttpBinding 二进制编码器的优点可以如此重要的是推荐的方法。 很容易即可更改该配置文件之间二进制和文本,来回切换。 调试 WCF 服务时,这很方便。 由 WCF 服务和客户端才支持二进制编码。 如果您需要非 WCF 客户端使用 WCF 服务应用程序,最好不使用二进制编码。

与文本数据的二进制数据

第一个演示将显示之间的差异,配置和使用 basicHttpBinding 和 WCF Silverlight 3 之间二进制消息编码之间的性能。 这篇文章中包含的示例应用程序中断的 (文本和二进制文件) 的两个示例出到独立的服务,可从相同 Silverlight 3 客户端调用。

示例应用程序的 Web.config 文件中的这些服务配置如 图 1 所示。 在文本和二进制编码的配置之间的差异正在于加粗。 注意服务 SpeedService0 使用该 basicHttpBinding 时 SpeedService1 一个 customBinding 使用名为 (前一代码示例所示) silverlightBinaryBinding 绑定配置,。

图 1 配置与二进制文件的文本

<services>
  <service 
behaviorConfiguration="SilverlightFaultData.Web.SpeedServiceBehavior" 
    name="SilverlightFaultData.Web.SpeedService0">
    <endpoint address="" binding="basicHttpBinding" 
      contract="SilverlightFaultData.Web.SpeedService0" />
    <endpoint address="mex" binding="mexHttpBinding" 
      contract="IMetadataExchange" />
  </service>
  <service
behaviorConfiguration="SilverlightFaultData.Web.SpeedServiceBehavior" 
    name="SilverlightFaultData.Web.SpeedService1">
    <endpoint address="" binding="customBinding" 
      bindingConfiguration="silverlightBinaryBinding" 
      contract="SilverlightFaultData.Web.SpeedService1" />
    <endpoint address="mex" binding="mexHttpBinding" 
      contract="IMetadataExchange" />
  </service>
</services>

服务 SpeedService0 和 SpeedService1 同时检索所有产品和每个产品的类别、 供应商和订单详细信息。 查询 (如 图 2 所示) 使用实体框架检索对象图。

检索的对象图的图 2

[OperationContract]
public IList<Products> DoWork()
{
    var ctx = new NorthwindEFEntities();
    var query = from p in ctx.Products
                .Include("Categories")
                .Include("Suppliers")
                .Include("OrderDetails")
                select p;
    var productList = query.ToList<Products>();
    return productList;
}

二进制消息编码的最佳方面之一就是只更改在配置文件中找到。 不需要进行更改代码。

当运行该示例应用程序时选择了编码文本选项 (如 图 3 所示) 时使用 basicHttpBinding 服务执行。 返回一个对象图,而且使用监视工具 (如 Fiddler 或 FireBug HTTP,结果会显示文本窗体中的对象图 4 MB 的大小,时间 850ms 检索。 在二进制编码选项进行选择时返回的对象图 3 MB,时间 600ms 检索。 这时使用 Northwind 数据库中一个中等大小的对象图的一个小示例结果是以行, Silverlight Web 服务团队的基准. 在此示例使用二进制编码中,对象图包含大约 2,300 总对象并按 25%的大小缩小,更快的文本编码 30%。

图 3 开始 BasicHttpBinding 通过数据

閿欒  娑堟伅是数据

当托管.NET Web 服务中引发异常时,它们不能被转换为一个 SOAP 消息,并传递回 Silverlight 2 客户端应用程序。 此外,Silverlight 2 无法读取 SOAP 错误。 上述两个问题会使调试 Web 服务与 Silverlight 2 困难。 由于不能 SOAP 错误使用 Silverlight 2,常见大多数 Silverlight 2 开发人员最终运行到访问 Web 服务时的错误消息是在臭名昭著"远程服务器返回错误: NotFound,"其中不包含任何 pratical 信息。 原始异常和它的详细信息不传输给 Silverlight 2 客户使调试 Web 服务很困难。 閿欒  娑堟伅包含通常在决定如何响应客户端应用程序的关键的数据。 渚嬪的方式  图 4 显示了调用 Web 服务,因为找不到数据库将引发异常的结果。

图 4 臭名昭著 NotFound 错误

当引发异常时,500 的 HTTP 状态代码返回到 Silverlight。 在浏览器的网络堆栈防止 Silverlight 读取响应状态代码 500,因此 SOAP 错误内的所有信息都是 Silverlight 客户端应用程序不可用。 即使该消息可以检索 Silverlight 2 不能转换回托管异常的错误。 这两个杩欎簺闂   宸插瑙 e 喅在 Silverlight 3。

解决问题

处理异常,WCF Silverlight 3 与需要处理这两个问题。 第一次,为网络浏览器堆栈防止 Silverlight 读取它不返回到 Silverlight 客户端的异常,状态代码必须更改从 500 允许读取响应的 Silverlight 内容。 这可通过从该 BehaviorExtensionElement 派生并实现 IEndpointBehavior 类,使得只要错误从 500 为前 200 更改状态代码来实现发生,并设置服务以使用在配置文件中的行为。 MSDN 文档包含一个 WCF 终结点行为可以能用于完成此,从而允许 Silverlight 客户端访问内容的错误。 下面的代码示例显示 SilverlightFaultBehavior 转换状态代码的类中的特定的代码:

public void BeforeSendReply(ref Message reply, object correlationState)
{
    if (reply.IsFault)
    {
        HttpResponseMessageProperty property = 
          new HttpResponseMessageProperty();
        // Here the response code is changed to 200.
        property.StatusCode = System.Net.HttpStatusCode.OK;
        reply.Properties[HttpResponseMessageProperty.Name] = property;
    }
}

下面的代码段中所示,可以在 Web.config 文件作为一个行为扩展引用 SilverlightFaultBehavior 类:

<extensions>
  <behaviorExtensions>
    <add name="silverlightFaults"
      type="SilverlightFaultBehavior.SilverlightFaultBehavior,
        SilverlightFaultBehavior, Version=1.0.0.0,
        Culture=neutral, PublicKeyToken=null" />
  </behaviorExtensions>
</extensions>

与就地在 SilverlightFaultBehavior,第二个问题获取 Silverlight 能够转换为一个托管的异常的错误,以便它能够读取它。 尽管这不是使用 Silverlight 2,3 Silverlight 现在能够处理错误。 这样,Silverlight 3 Web 服务中引发的异常时向用户读取一个容错和存在相应的信息。

阅读 Silverlight 3 中的异常信息的整个过程会如下所示:

1) 异常引发 Web 服务中。

2) 此服务使用在 SilverlightFaultBehavior 500 HTTP 状态代码转换为 200。

3) 转换成一个 SOAP 错误,传递到 Silverlight 3 客户端异常。

4) 浏览器允许阅读邮件,因为它有一个状态代码 200 的 Silverlight。

5) 3 Silverlight 应用程序中的代码检查以查看它是否一个 FaultException 或一个 FaultException <exceptiondetail> 错误的类型。

声明的错误

基于 SOAP 的 WCF 服务进行通信使用 SOAP 错误的消息的错误或.NET 托管异常。 因此,.NET 托管异常将被转换到传递到客户端,一个 SOAP 错误,并且再转换的回.NET 托管异常。

错误可以是未声明或声明的并且所有都强类型化的。 声明的错误没有指定操作合同中,只应进行调试。 声明的错误返回异常消息给客户端完全引发 Web 服务中。 若要是未声明的错误配置元素的 includeExceptionDetailInFaults 属性必须设置为 true,如下所示:

<serviceDebug> 
<behavior name="SilverlightFaultData.Web.Service1Behavior">
  <serviceMetadata httpGetEnabled="true" />
  <serviceDebug includeExceptionDetailInFaults="true" />
</behavior>

示例应用程序的 Service1 使用这种行为允许该异常将被自动转换为一个 FaultException <exceptiondetail>。 Silverlight 3 客户端可以然后检查其异步完成的事件处理程序中 e.Error 参数的并按在下面的代码和 图 5 中所显示执行适当的操作中:

if (e.Error != null) {
    ErrorPanel.DataContext = e.Error;
    if (e.Error is FaultException<ExceptionDetail>) {
        var fault = e.Error as FaultException<ExceptionDetail>;
        ErrorPanel.DataContext = fault;
    }
}

fig07.gif

图 5 声明的 FaultException

未声明的错误显示在其原始状态的所有困难的错误信息不很明显是向用户显示一个好主意的异常。 由于这个原因不建议使用生产应用程序中的未声明的错误。 托管的异常可太包含内部应用程序信息 (有时敏感信息)。 在 includeExceptionDetailInFaults 设置为 true 只应暂时调试的应用程序错误时而不要在生产环境。 强烈建议在 includeExceptionDetailInFaults 设置为 false 生产应用程序。

声明的错误

服务操作用一个 FaultContractAttribute (或在 FaultContractAttribute 的派生的类型) 修饰时会创建一个已声明的错误。 与未声明的错误,不同声明的错误是适用于生产它们专门翻译为错误类型的代码中的异常的信息。 在 Web 服务开发人员可以创建在代码中的错误类型以及设置其属性与适用于发送到 Silverlight 的信息。 客户端必须知道的信息应只填充该错误。 任何敏感 (凭据之类的信息) 不应发送到客户端的错误。 在 Silverlight 客户端开发人员可以编写代码以查找该类型,并告诉用户适当的内容。

图 6 显示了正在使用类型为 DataFault FaultContract 属性修饰该服务操作。 在常规 FaultContract <typeof(ExceptionDetail)> 可能已使用,但建议为操作中使用特定的自定义错误类型。 在这种情况下,操作将使用示例应用程序中创建 DataFault 类型。 此服务操作将失败,因为找不到该数据库。 将引发异常,然后捕获该 try/catch 块位置读取异常,并密钥信息放入该 DataFault 之前引发。 到目前为止,DataFault 转换成一个 SOAP 错误,状态代码 200 Silverlight 客户端发送回。

图 6 创建一个声明的错误

[OperationContract]
[FaultContract(typeof(DataFault))]
public IList<Products> DoWork()
{
    try
    {
        var ctx = new NorthwindEFEntities();
        var query = from p in ctx.Products
                    select p;
        return query.ToList<Products>();
    }
    catch (Exception ex)
    {
        DataFault fault = new DataFault { Operation = Operation.Other, Description = ex.Message };
        throw new FaultException<DataFault>(fault, "because");
    }
}

DataFault 类 (如 图 7 所示) 定义的操作属性和说明属性。 错误包含的属性是开发人员。 属性应代表错误的重要信息,以便它可以检查由 Silverlight 客户端。 操作设置为一个自定义枚举的类型将指示异常发生时正在执行的 SQL 操作的类型的操作 (还图 7 所示)。 到自定义消息,而不以避免发送任何敏感信息异常消息应设置的说明。 (示例应用程序使用 ex.Message 只是出于演示目的。 我建议不要将异常的消息直接传递给 Silverlight 客户端)。 在 FaultException 也接受代表异常原因的参数。 在该的示例原因设置为"因为。" 原因可用于帮助客户端分类异常的原因。

图 7 DataFault 类

public class DataFault
{
    public Operation Operation { get; set; }
    public string Description { get; set; }
}

public enum Operation
{
    Select,
    Insert,
    Update,
    Delete,
    Other
}

该示例的 Service3 都有其终结点表示在 behaviorConfiguration 应使用 SilverlightFaultBehavior 类 (转换为 200 从 500 状态代码) 配置。 配置如下所示:

<service
  behaviorConfiguration="SilverlightFaultData.Web.Service3Behavior"
  name="SilverlightFaultData.Web.Service3">
  <endpoint address=""
    behaviorConfiguration="SilverlightFaultBehavior"
    binding="customBinding" bindingConfiguration="silverlightBinaryBinding"
    contract="SilverlightFaultData.Web.Service3" />
  <endpoint address="mex" binding="mexHttpBinding"
    contract="IMetadataExchange" />
</service>

在执行使用声明的错误的服务时 Silverlight 客户端接收,并可以读取错误。 异步 Web 服务操作完成时执行下面的代码:

if (e.Error is FaultException<ServiceReference3.DataFault>)
{
    var fault = e.Error as FaultException<ServiceReference3.DataFault>;
    ErrorPanel.DataContext = fault;
}

显示错误消息以查看它是否一个 FaultException DataFault 类型的检查。 如果它是,然后可以检查单个属性操作和说明。 图 8 显示了 DataFault 的直接向用户显示的自定义信息。

fig10.gif

图 8 分析声明的错误

在生产的应用程序中应映射到 SOAP 错误的一些例外情况被设计一个自定义错误策略。 此密钥确定在其下的异常应映射到错误情况。 这取决于是否应通知客户端应用程序在特定信息的错误在服务器上。

上的换行

本文说明 3 Silverlight 应用程序可以从二进制编码和异常管理功能中获益如何。 使用.NET WCF 客户端,如 Silverlight 时二进制消息编码通过 basicHttpBinding 是实心的选择。 异常通常包括可帮助在调试应用程序的关键信息。 本文介绍了如何表面开发和生产环境中,使用 Silverlight 3 增强功能的异常信息。

将您的问题和提出发送到同样的 mmdata@microsoft.com".

John Papa ( johnpapa。 网络) 是高级顾问,用户花在夏季里住宿的与他的家人 Yankees 定位棒球风扇。 同样,Silverlight MVP,Silverlight 内幕和 INETA 演讲者具有编写几个简介册包括其最新,标题 Data-Driven Services with Silverlight 2 (O'Reilly,2009年)。 他经常说出会议,如 VSLive!,DevConnections,和 MIX。