C# 对于异常,WCF始终返回400
我有一个RESTful WCF服务,并实现了一个ErrorHandler,如以下所示:C# 对于异常,WCF始终返回400,c#,wcf,rest,C#,Wcf,Rest,我有一个RESTful WCF服务,并实现了一个ErrorHandler,如以下所示: public class MyErrorHandler : IErrorHandler, IServiceBehavior { // OMITTED: IServiceBehavior Members public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
public class MyErrorHandler : IErrorHandler, IServiceBehavior
{
// OMITTED: IServiceBehavior Members
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
DoSomeCustomLogging(error);
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
}
}
它连接在我的web.config中,如下所示:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="Rest">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name ="errorHandler" type="ACME.MyErrorHandlerElement, ACME.MyErrorHandler"/>
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" faultExceptionEnabled="false" helpEnabled="false" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
出于某种原因,如果我的服务抛出异常,则会将400而不是500返回给客户端。知道为什么吗?您需要修改通过引用传入的错误,这不是常规的webmethod调用
#Region "IErrorHandler Members"
Public Function HandleError(ByVal [error] As Exception) As Boolean Implements IErrorHandler.HandleError
Console.WriteLine("HandleError called.")
' Returning true indicates you performed your behavior.
Return True
End Function
' This is a trivial implementation that converts Exception to FaultException<GreetingFault>.
Public Sub ProvideFault(ByVal [error] As Exception, ByVal ver As MessageVersion, ByRef msg As Message) Implements IErrorHandler.ProvideFault
Console.WriteLine("ProvideFault called. Converting Exception to GreetingFault....")
Dim fe As New FaultException(Of GreetingFault)(New GreetingFault([error].Message))
Dim fault As MessageFault = fe.CreateMessageFault()
msg = Message.CreateMessage(ver, fault, "http://microsoft.wcf.documentation/ISampleService/SampleMethodGreetingFaultFault")
End Sub
#End Region
#区域“IErrorHandler成员”
作为布尔值的公共函数HandleError(ByVal[error]作为例外)实现了IErrorHandler.HandleError
Console.WriteLine(“调用了HandleError”)
'返回true表示您执行了自己的行为。
返回真值
端函数
'这是一个将异常转换为FaultException的简单实现。
Public Sub ProvideFault(ByVal[error]作为例外,ByVal ver作为MessageVersion,ByRef msg作为Message)实现了IErrorHandler.ProvideFault
Console.WriteLine(“调用了ProviderDefault。将异常转换为GreetingFault…”)
Dim fe作为新的故障异常(GreetingFault的)(新的GreetingFault([error].Message])
作为MessageFault=fe.CreateMessageFault()的Dim故障
msg=Message.CreateMessage(版本,错误,“http://microsoft.wcf.documentation/ISampleService/SampleMethodGreetingFaultFault")
端接头
#末端区域
有好消息也有坏消息。好消息是,如果您的配置是正确的,那么您的代码就可以工作了。我马上提供一个解决方案。坏消息是这个解决方案可能不稳定。根据MSDN文档,可能会命中,从而访问像
WebOperationContext.Current
这样的内容
这就是说,以下是可以让您修复的:
您没有看到预期的结果,因为您的配置是错误的。您的配置正确地声明了扩展,但并不需要声明任何端点都应该使用它。在两个星号注释之间是我插入到您的配置中的修复程序:
<system.serviceModel>
<!-- ****************** -->
<behaviors>
<serviceBehaviors>
<behavior>
<errorHandler />
</behavior>
</serviceBehaviors>
</behaviors>
<!-- ****************** -->
<extensions>
<behaviorExtensions>
<add name ="errorHandler" type="ACME.MyErrorHandlerElement, ACME.MyErrorHandler"/>
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" faultExceptionEnabled="false" helpEnabled="false" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
上面的代码确保您不会意外重写由服务操作开发人员显式设置的状态代码。它还允许开发人员抛出的WebFaultException错误与开发人员分配的任何状态代码一起传播。您的webconfig丢失,请在配置文件中更新,类型为MyErrorHandlerElement-是否应为MyErrorHandler?Eric,在类型中,第一项为ErrorHandlerElement(我已经更新了我的示例以包含它)第二个是程序集名称。在实现这一点时,我现在看到在由服务方法调用的业务组件中引发异常时返回200,这也不理想。但是,当由服务方法本身引发异常时,这很好(返回500)。
<system.serviceModel>
<!-- ****************** -->
<behaviors>
<serviceBehaviors>
<behavior>
<errorHandler />
</behavior>
</serviceBehaviors>
</behaviors>
<!-- ****************** -->
<extensions>
<behaviorExtensions>
<add name ="errorHandler" type="ACME.MyErrorHandlerElement, ACME.MyErrorHandler"/>
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" faultExceptionEnabled="false" helpEnabled="false" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
var faultEx = error as FaultException;
bool isRest = version == MessageVersion.None;
if (isRest && faultEx == null)
{
OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
if (response.StatusCode == HttpStatusCode.BadRequest) {
response.StatusCode = HttpStatusCode.InternalServerError;
}
}
}