2

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

我在 Web 服务中有一个简单的 Hello Web 方法,它只返回一个字符串,不做任何其他事情(没有日志记录、异常处理,什么都不做)。我从 Visual Studio 中运行 WCFTestClient,方法是选择 .svc 文件并单击 F5 开始调试。当 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()

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

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

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

  1. 定义 DEBUG 常量:在 Debug 模式下设置为 on,在 Release 中设置为 off;

  2. 优化代码:在Debug模式下开启,在Release模式下开启;

  3. 高级 > 输出调试信息:在 Debug 模式下设置为 full,在 Release 中设置为 pdb-only。

尝试在发布模式下更改构建属性,我发现只有在优化代码设置为关闭并且高级>输出调试信息设置为完整时,我才能使 web 方法工作。将 DEBUG 常量设置为 on 或 off 没有区别。

有谁知道为什么打开代码优化或将调试信息设置为仅 pcb 时简单的 Web 方法会失败?

4

3 回答 3

2

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

为了重新创建一个可以工作的示例项目,我创建了一个具有以下服务接口的 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);
        }
    }
}

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

    <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 测试客户端

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

HTH。

于 2013-05-22T23:39:36.257 回答
2

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

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

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

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

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

于 2013-05-23T03:13:56.867 回答
1

我在 WPF 应用程序中遇到了类似的问题。程序可以在 Debug 中完美运行,但在 Release 或 Published 中则不行。

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

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

希望这可以帮助某人。

于 2020-03-11T06:30:26.640 回答