在之前的例子中,我们调用了一个向服务层引发一个未处理异常的服务,客户端接收到的最小信息在图片10.1显示。默认情况下,WCF 会向一个调用方转发这条消息,但不是这条异常消息的细节,这是为了阻止有关系统实现或者结构信息的明暗细节暴露出来。
ServiceDebugBehavior有一个可以用来开启向客户端传递异常细节的IncludeExceptionDetailInFaults属性。类似列表10.4修改你的工程的app.config 文件来开启这个行为。
列表10.4 通过配置文件开启IncludeExceptionDetailInFaults 选项
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadata">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="metadata" name="ServiceLibrary.Service1">
<endpoint address="" binding="mexHttpBinding" bindingConfiguration=""
contract="ServiceLibrary.IService" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/divideService" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
在IncludeExceptionDetailInFaults 选项开启了以后,再次运行示例服务并且对被除数提供一个0值,这将导致显示类似于图片10.3的消息。
图片10.3 包含ServiceDebugBehavior 的异常细节
注意你也可以在服务定义中使用ServiceBehaviorAttribute来设置这个行为。例如,我们可以通过将Service.cs改成类似列表10.5 来开启通信过程中的调试信息。
列表10.5 使用ServiceBehaviorAttribute 来开启IncludeExceptionDetailInFaults
namespace ServiceLibrary
{
[ServiceContract]
public interface IService
{
[OperationContract]
double Divide(double numerator, double denominator);
}
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class Service1 : IService
{
public double Divide(double numerator, double denominator)
{
if (denominator == 0)
{
throw new ArgumentOutOfRangeException("denominator", "Must be a numeric value less than or greator than zero");
}
return numerator / denominator;
}
}
}
注意在行为中使用这个属性来开启异常细节将覆盖配置文件中任何想禁用这个特性的其他设置(请看第一个回复)。因此,我们强烈建议你在生产应用中使用一个基于配置文件的方法,或者可以在开发过程中保留使用这个属性。
无论你选择配置文件还是选择属性设置来使用这个特性,记住要禁用这个选项当你不需要异常细节被传输时。仅当必要的时候才使用这个选项将帮助你来保证服务明暗细节不会暴露出来。