我遇到了一个奇怪的问题:我正在构建的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模式之间看到的唯一区别是:
定义DEBUG常量:在调试模式下设置,在发布时关闭;
优化代码:在调试模式下启动,在发布中启用;
高级>输出调试信息:在调试模式下设置为完全,在发布模式下设置为pdb。
尝试在发布模式下更改构建属性,我发现只有在设置了Optimize代码并且Advanced>时才能使web方法起作用。输出调试信息设置为完整。打开或关闭DEBUG常量没有区别。
有没有人知道为什么在打开代码优化时,或者当调试信息设置为仅限pcb时,简单的Web方法会失败?
答案 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测试客户端在调试和发布模式下构建和运行服务,它按预期工作:
我还能够使用IE(http://localhost:<port-number)/HelloService.svc
)ping服务,并且能够看到服务信息页面并访问其MEX。
HTH。
答案 2 :(得分:1)
我对WPF应用程序有类似的问题。程序可以在Debug中完美运行,但不能在Release中或发布时完美运行。
发现.json文件未包含在发布/发布中。
解决方案是在解决方案资源管理器中单击.json文件,将“文件属性”中的“生成操作”更改为“内容”,然后进行生成/发布。
希望这对某人有帮助。