WCF服务在调试模式下运行,但在Release中不运行

时间:2013-05-22 22:38:16

标签: .net wcf

我遇到了一个奇怪的问题:我正在构建的WCF Web服务在调试模式下运行但在发布时没有运行。

我在Web服务中有一个简单的Hello Web方法,只返回一个字符串,不执行任何操作(没有记录,异常处理,没有)。我通过选择.svc文件并单击F5开始调试,从Visual Studio中运行WCFTestClient。当WCFTestClient打开时,我双击Hello Web方法并调用它。在调试模式下运行正常。在发布模式下,我几乎立即收到以下错误:

Object reference not set to an instance of an object.

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at IVehicleRisk.Hello()
   at VehicleRiskClient.Hello()

(网络服务是VehicleRisk.svc,服务合同是IVehicleRisk)。

向应用程序添加断点我在调用Hello Web方法时可以看到正在调用Global.asax.cs中的Application_BeginRequest方法(它是一个空方法)。当抛出异常时,在构造函数或Hello方法中没有命中VehicleRisk.svc.cs中的断点(当Web方法工作时,正在命中断点)。

我查看了Visual Studio中的项目构建属性(在解决方案资源管理器中右键单击项目,选择“属性”,在“属性”窗口中打开“构建”选项卡)。我可以在Debug和Release模式之间看到的唯一区别是:

  1. 定义DEBUG常量:在调试模式下设置,在发布时关闭;

  2. 优化代码:在调试模式下启动,在发布中启用;

  3. 高级>输出调试信息:在调试模式下设置为完全,在发布模式下设置为pdb。

  4. 尝试在发布模式下更改构建属性,我发现只有在设置了Optimize代码并且Advanced>时才能使web方法起作用。输出调试信息设置为完整。打开或关闭DEBUG常量没有区别。

    有没有人知道为什么在打开代码优化时,或者当调试信息设置为仅限pcb时,简单的Web方法会失败?

3 个答案:

答案 0 :(得分:2)

事实证明问题与WCF本身无关。

我在服务类中调用了一个简单的Hello方法,但该类的构造函数正在设置日志记录(尽管我实际上并没有使用Hello方法中的日志记录)。在服务类构造函数中实例化的日志记录助手类具有方法GetCallingMethodName。此方法遍历堆栈跟踪以确定记录消息的类和方法的名称,以在日志消息中包含名称。

问题的关键是GetCallingMethodName跳过堆栈跟踪中的第一个方法调用,通常是GetCallingMethodName方法本身。 Web服务器上的64位JIT编译器必须一直在内联方法,因此堆栈跟踪中没有第二个堆栈帧。因此,尝试跳过堆栈跟踪中的第一帧会导致错误。

解决方案是从第一个堆栈帧而不是第二个堆栈帧开始遍历堆栈跟踪。

在调试模式下将Web服务部署到服务器时未出现此问题,因为编译器优化已关闭,因此编译器无法内联该方法。它也没有出现在我的开发PC上,因为32位JIT编译器必须以不同于服务器上64位编译器的方式优化代码。

答案 1 :(得分:1)

如果没有看到您的代码,很难说出可能出现的问题。

要重新创建一个有效的示例项目,我使用以下服务接口创建了一个WCF服务应用程序:

using System.ServiceModel;

namespace HelloWCF
{
    [ServiceContract]
    public interface IHelloService
    {
        [OperationContract]
        string SayHello(string name);
    }
}

然后我用以下类实现了这个接口:

namespace HelloWCF
{
    public class HelloService : IHelloService
    {
        public string SayHello(string name)
        {
            return string.Format("Hello, {0}", name);
        }
    }
}

我还将以下服务配置添加到web.config的<system.servicemodel>部分:

    <services>
        <service name="HelloWCF.HelloService" 
                 behaviorConfiguration="SimpleBehavior">
            <endpoint 
                 binding="basicHttpBinding" 
                 contract="HelloWCF.IHelloService" />
            <endpoint 
                 address="mex" 
                 binding="mexHttpBinding" 
                 contract="IMetadataExchange" />
        </service>
    </services>

我还命名了服务行为:

<behaviors>
    <serviceBehaviors>
        <behavior name="SimpleBehavior">
            <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
            <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
            <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
            <serviceDebug includeExceptionDetailInFaults="false"/>                    
        </behavior>
    </serviceBehaviors>
</behaviors>

我使用WCF测试客户端在调试和发布模式下构建和运行服务,它按预期工作: WCF Test Client

我还能够使用IE(http://localhost:<port-number)/HelloService.svc)ping服务,并且能够看到服务信息页面并访问其MEX。

HTH。

答案 2 :(得分:1)

我对WPF应用程序有类似的问题。程序可以在Debug中完美运行,但不能在Release中或发布时完美运行。

发现.json文件未包含在发布/发布中。

解决方案是在解决方案资源管理器中单击.json文件,将“文件属性”中的“生成操作”更改为“内容”,然后进行生成/发布。

希望这对某人有帮助。