一些上下文:我们有一个自定义 XSD 并使用 WSCF.blue 生成 WSDL 和 C# 代码。客户端使用 ChannelFactory<T>
并共享接口(interface),其中包括 WSCF.blue 添加的所有属性以匹配 XSD 中的内容。
我正在尝试实现 IErrorHandler.ProvideFault
,它提供了一个通用的 FaultException<T>
,但在客户端我得到了一个非通用的 FaultContract
。这是我的 ProvideFault
方法的样子:
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (!(error is FaultException))
{
FaultException faultException = FaultExceptionFactory.CreateFaultException(error);
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
在每个服务方法中,如果我使用
throw FaultExceptionFactory.CreateFaultException(ex)
进行 try/catch 它会按预期工作,所以我认为 [FaultContract]
、工厂、绑定(bind)等都是正确的。以防万一,这就是工厂的工作方式:BusinessRuleFaultExceptionType businessRuleFaultException = new BusinessRuleFaultExceptionType();
BusinessRuleFaultException.Code = exception.Code.ToString();
BusinessRuleFaultException.Reason = exception.Message;
return new FaultException<BusinessRuleFaultExceptionType>(
businessRuleFaultException,
exception.Message,
new FaultCode(exception.Code.ToString())
);
我认为问题在于如何在
IErrorHandler
中创建消息,也许在 CreateMessageFault()
中。我读过操作应该是 faultException.Action
而不是 null
,但实际上 faultException.Action
是 null
。也许这是导致问题的原因。我可以在工厂中设置一个 Action ,但是该 Action 应该是什么,为什么手动 throw 时不显示?我可能缺少的任何其他想法?
编辑:
我检查了 WSDL 并找到了我正在调用的特定操作及其操作:
<wsdl:operation name="MyMethod">
<wsdl:fault wsaw:Action="http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault" name="BusinessRuleFaultExceptionTypeFault" message="tns:..."/>
我尝试对 action:
Message.CreateMessage(..., "http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault")
进行硬编码并将其设置为工厂中的 .Action
,但这仍然不起作用。编辑 2:
throw/catch 生成以下 XML,它允许捕获客户端上的通用异常:
<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns="http://myNamespace/Services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Code xmlns="http://myNamespace/Entitites">-100</Code>
<Reason xmlns="http://myNamespace/Entitites">xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
IHttpErrorHandler
生成以下内容,这些内容转到非通用 FaultException
:<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns="http://schemas.datacontract.org/2004/07/My.Dot.Net.Namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<codeField>-100</codeField>
<reasonField>xxx</reasonField>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
编辑 3:
如果我将
[DataContract]
和 [DataMember]
添加到 BusinessRuleFaultExceptionType
,那么我会得到几乎正确的 XML:<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns="http://myNamespace/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Code>-100</Code>
<Reason>xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
它缺少代码和原因的命名空间。至少我认为这缩小了范围。常规序列化使用
[XmlType]
和 [XmlElement]
,而 IErrorHandler
使用 [DataContract]
和 [DataMember]
。不幸的是 [DataMember]
不允许你设置命名空间,所以我认为现在的问题是如何在 IErrorHandler
中使用 XMLSerializer 。这描述了我的问题,但由于上述原因,此修复程序不起作用:http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html编辑 4:
我部分地发现了这个问题。我们正在使用
XmlSerializer
,但由于 IErrorHandler
超出了操作范围,它会恢复为默认的 DataContractSerializer
。解决方案是更改您的服务以在任何地方使用 DataContractSerializer
,或者在创建故障时手动选择 XmlSerializer
。这两篇文章提供了我所需要的:http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html
http://zamd.net/2008/08/15/serializing-faults-using-xmlserializer/
这让我非常接近。它与工作 XML 相同,除了缺少异常类型的命名空间:
<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Code xmlns="http://myNamespace/Entitites">-100</Code>
<Reason xmlns="http://myNamespace/Entitites">xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
我假设它没有添加
xmlns="http://myNamespace/Services"
因为它没有请求的上下文。该 namespace 是在接口(interface)中定义的,而不是在数据协定中定义的。我真的会被迫留在请求的上下文中(希望 IOperationInvoker
有效),而不是使用 IHttpHandler
吗? 最佳答案
我对 WSCF.blue 没有任何经验,因此我尝试制作一个示例应用程序来演示使用标准 WCF 客户端和服务器的工作场景。也许它将帮助您找到丢失的连接以使您的方案工作。
我将您的 BusinessRuleFaultExceptionType 与 代码 和 Reason 属性一起使用。 BusinessRuleFaultExceptionType
是 WCF 故障合约。
我有点懒惰,在单个控制台应用程序中实现了所有代码。 Wcf 客户端使用与 Wcf 服务相同的 Datacontracts 和 ICalculator
接口(interface)。对不起代码。这将是一个很长的帖子。
首先是数据契约和服务接口(interface)
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
[ServiceContract(Namespace = "http://UE.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Add(double n1, double n2);
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Subtract(double n1, double n2);
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Multiply(double n1, double n2);
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Divide(double n1, double n2);
}
/// <summary>
/// General fault structure.
/// </summary>
[DataContract(Namespace = "http://someurl.temp")]
public sealed class BusinessRuleFaultExceptionType
{
[DataMember]
public int Code { get; set; }
[DataMember]
public string Reason { get; set; }
}
现在,服务实现:
[ErrorBehavior(typeof(MyErrorHandler))]
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
throw new ArgumentException("My exception");
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
和客户端实现:
public class Client : ClientBase<ICalculator>, ICalculator
{
public double Add(double n1, double n2)
{
try
{
return base.Channel.Add(n1, n2);
}
catch (FaultException<BusinessRuleFaultExceptionType> ex)
{
Console.WriteLine("This is my Code: {0}. This is the reason: {1}", ex.Detail.Code, ex.Detail.Reason);
}
catch (Exception ex)
{
throw;
}
return 0;
}
public double Subtract(double n1, double n2)
{
throw new NotImplementedException();
}
public double Multiply(double n1, double n2)
{
throw new NotImplementedException();
}
public double Divide(double n1, double n2)
{
throw new NotImplementedException();
}
}
演示此示例的主程序
internal class Program
{
private static void Main(string[] args)
{
ServiceHost myServiceHost = new ServiceHost(typeof(CalculatorService));
// Open the ServiceHostBase to create listeners and start listening for messages.
myServiceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
Console.WriteLine("Sending data from client to service.");
Client c = new Client();
var res = c.Add(1, 2);
Console.ReadLine();
}
}
错误处理的实现:
/// <summary>
/// Helper class for exception repackaging.
/// </summary>
internal class MyExceptionHandler
{
/// <summary>
/// Handles thrown exception into internal exceptions that are being sent over to client.
/// </summary>
/// <param name="error">Exception thrown.</param>
/// <returns>Repackaged exception.</returns>
internal static Exception HandleError(Exception error)
{
// could do something here.
return error;
}
}
#region Behaviour
/// <summary>
/// Control the fault message returned to the caller and optionally perform custom error processing such as logging.
/// </summary>
public sealed class MyErrorHandler : IErrorHandler
{
/// <summary>
/// Provide a fault. The Message fault parameter can be replaced, or set to null to suppress reporting a fault.
/// </summary>
/// <param name="error">The <see cref="Exception"/> object thrown in the course of the service operation.</param>
/// <param name="version">The SOAP version of the message.</param>
/// <param name="fault">The <see cref="System.ServiceModel.Channels.Message"/> object that is returned to the client, or service, in the duplex case.</param>
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
//If it's a FaultException already, then we have nothing to do
if (error is FaultException)
return;
error = MyExceptionHandler.HandleError(error);
var serviceDebug = OperationContext.Current.EndpointDispatcher.ChannelDispatcher.IncludeExceptionDetailInFaults;
BusinessRuleFaultExceptionType f = new BusinessRuleFaultExceptionType
{
Code = -100,
Reason = "xxx"
};
FaultException<BusinessRuleFaultExceptionType> faultException = new FaultException<BusinessRuleFaultExceptionType>(f, error.Message);
MessageFault faultMessage = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, faultMessage, faultException.Action);
}
/// <summary>
/// Enables error-related processing and returns a value that indicates whether the dispatcher aborts the session and the instance context in certain cases.
/// </summary>
/// <param name="error">The exception thrown during processing.</param>
/// <returns>true if Windows Communication Foundation (WCF) should not abort the session (if there is one) and instance context if the instance context is not Single; otherwise, false. The default is false.</returns>
public bool HandleError(Exception error)
{
// could use some logger like Nlog but as an example it will do.
Console.WriteLine("Error occured. {0}", error);
return true;
}
}
/// <summary>
/// This attribute is used to install a custom error handler for a service
/// </summary>
public sealed class ErrorBehaviorAttribute : Attribute, IServiceBehavior
{
/// <summary>
/// Type of component to which this error handled should be bound
/// </summary>
private readonly Type errorHandlerType;
/// <summary>
/// Initializes a new instance of the ErrorBehaviorAttribute class.
/// </summary>
/// <param name="errorHandlerType">Type of component to which this error handled should be bound</param>
public ErrorBehaviorAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
/// <summary>
/// Type of component to which this error handled should be bound
/// </summary>
public Type ErrorHandlerType
{
get { return errorHandlerType; }
}
/// <summary>
/// Provides the ability to inspect the service host and the service description to confirm that the service can run successfully.
/// </summary>
/// <param name="description">
/// <para>Type: <see cref="System.ServiceModel.Description.ServiceDescription"/></para>
/// <para>The service description.</para>
/// </param>
/// <param name="serviceHostBase">
/// <para>Type: <see cref="System.ServiceModel.ServiceHostBase"/></para>
/// <para>The service host that is currently being constructed.</para>
/// </param>
void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
/// <summary>
/// Provides the ability to pass custom data to binding elements to support the contract implementation.
/// </summary>
/// <param name="description">
/// <para>Type: <see cref="System.ServiceModel.Description.ServiceDescription"/></para>
/// <para>The service description.</para>
/// </param>
/// <param name="serviceHostBase">
/// <para>Type: <see cref="System.ServiceModel.ServiceHostBase"/></para>
/// <para>The host of the service.</para>
/// </param>
/// <param name="endpoints">
/// <para>Type: <see cref="System.Collections.ObjectModel.Collection<ServiceEndpoint>"/></para>
/// <para>The service endpoints.</para>
/// </param>
/// <param name="parameters">
/// <para>Type: <see cref="System.ServiceModel.Channels.BindingParameterCollection"/></para>
/// <para>Custom objects to which binding elements have access.</para>
/// </param>
void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
/// <summary>
/// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, message or parameter interceptors, security extensions, and other custom extension objects.
/// </summary>
/// <param name="description">
/// <para>Type: <see cref="System.ServiceModel.Description.ServiceDescription"/></para>
/// <para>The service description.</para>
/// </param>
/// <param name="serviceHostBase">
/// <para>Type: <see cref="System.ServiceModel.ServiceHostBase"/></para>
/// <para>The host that is currently being built.</para>
/// </param>
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
try
{
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
}
catch (MissingMethodException e)
{
throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must have a public empty constructor.", e);
}
catch (InvalidCastException e)
{
throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
}
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
#endregion
我的控制台应用程序的 app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<client>
<endpoint address="http://localhost:12345/service/calc" binding="basicHttpBinding" contract="ConsoleApplication2.ICalculator" >
</endpoint>
</client>
<services>
<service name="ConsoleApplication2.CalculatorService" behaviorConfiguration="service">
<endpoint address="http://localhost:12345/service/calc" binding="basicHttpBinding" contract="ConsoleApplication2.ICalculator" >
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:12345/service/calc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="service">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我使用 WCF 测试客户端发送此请求:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://UE.ServiceModel.Samples/ICalculator/Add</Action>
</s:Header>
<s:Body>
<Add xmlns="http://UE.ServiceModel.Samples">
<n1>0</n1>
<n2>1</n2>
</Add>
</s:Body>
</s:Envelope>
并得到了这个回应:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="sk-SK">My exception</faultstring>
<detail>
<BusinessRuleFaultExceptionType xmlns="http://someurl.temp" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Code>-100</Code>
<Reason>xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
当我打电话
Client c = new Client();
var res = c.Add(1, 2);
我捕获了登录到控制台的
FaultException<BusinessRuleFaultExceptionType> ex
Console.WriteLine("This is my Code: {0}. This is the reason: {1}", ex.Detail.Code, ex.Detail.Reason);
编辑:我更改了
BusinessRuleFaultExceptionType
中的命名空间并将解决方案设置为使用 [XmlSerializerFormat(SupportFaults = true)]
。更改了接口(interface)、数据契约和服务实现:
[ServiceContract(Namespace = "http://UE.ServiceModel.Samples")]
[XmlSerializerFormat(SupportFaults = true)]
public interface ICalculator
{
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Add(double n1, double n2);
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Subtract(double n1, double n2);
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Multiply(double n1, double n2);
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(BusinessRuleFaultExceptionType))]
double Divide(double n1, double n2);
}
/// <summary>
/// General fault structure.
/// </summary>
[DataContract(Name = "BusinessRuleFaultExceptionType", Namespace = "http://someurl.temp")]
[XmlType("BusinessRuleFaultExceptionType", Namespace = "http://someurl.temp")]
public sealed class BusinessRuleFaultExceptionType
{
//[DataMember]
[XmlElement(IsNullable = false,Namespace = "http://namespaces2.url")]
public int Code { get; set; }
[XmlElement(IsNullable = false, Namespace = "http://namespaces2.url")]
public string Reason { get; set; }
}
[ErrorBehavior(typeof(MyErrorHandler))]
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
throw new FaultException<BusinessRuleFaultExceptionType>(new BusinessRuleFaultExceptionType()
{
Code = -100,
Reason = "xxx"
});
//throw new ArgumentException("My exception");
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
我找到了一篇关于 there are problems 在 IErrorHandler 中使用 XmlSerializer 的原因的文章。因此,我已将服务实现更改为在方法实现中抛出 FaultException 并且不依赖于 IErrorHandler。
我还发现了另一篇(相对较旧的)文章 how to use XmlSerializer in IErroHandler,一段时间后,我甚至可以从 IErrorHandler 进行序列化。我将 trown 异常改回了 ArgumentException。
这是所做的更改(我继续前面的示例,因此可能并不需要所有代码和属性):
[DataContract(Name = "BusinessRuleFaultExceptionType", Namespace = "http://someurl.temp")]
[XmlType("BusinessRuleFaultExceptionType", Namespace = "http://someurl.temp")]
[XmlRoot("BusinessRuleFaultExceptionType", Namespace = "http://someurl.temp")]
public sealed class BusinessRuleFaultExceptionType
{
//[DataMember]
[XmlElement(IsNullable = false, Namespace = "http://namespaces2.url")]
public int Code { get; set; }
[XmlElement(IsNullable = false, Namespace = "http://namespaces2.url")]
public string Reason { get; set; }
}
public class XmlSerializerMessageFault : MessageFault
{
FaultCode code;
FaultReason reason;
object details;
public XmlSerializerMessageFault(FaultCode code, FaultReason reason, object details)
{
this.details = details;
this.code = code;
this.reason = reason;
}
public override FaultCode Code
{
get { return code; }
}
public override bool HasDetail
{
get { return (details != null); }
}
protected override void OnWriteDetailContents(System.Xml.XmlDictionaryWriter writer)
{
var ser = new XmlSerializer(details.GetType());
ser.Serialize(writer, details);
writer.Flush();
}
public override FaultReason Reason
{
get { return reason; }
}
}
/// <summary>
/// Control the fault message returned to the caller and optionally perform custom error processing such as logging.
/// </summary>
public sealed class MyErrorHandler : IErrorHandler
{
/// <summary>
/// Provide a fault. The Message fault parameter can be replaced, or set to null to suppress reporting a fault.
/// </summary>
/// <param name="error">The <see cref="Exception"/> object thrown in the course of the service operation.</param>
/// <param name="version">The SOAP version of the message.</param>
/// <param name="fault">The <see cref="System.ServiceModel.Channels.Message"/> object that is returned to the client, or service, in the duplex case.</param>
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
BusinessRuleFaultExceptionType f = new BusinessRuleFaultExceptionType
{
Code = -100,
Reason = "xxx"
};
// create a fault message containing our FaultContract object
FaultException<BusinessRuleFaultExceptionType> faultException = new FaultException<BusinessRuleFaultExceptionType>(f, error.Message);
MessageFault faultMessage = faultException.CreateMessageFault();
var msgFault = new XmlSerializerMessageFault(faultMessage.Code, faultMessage.Reason, f);
fault = Message.CreateMessage(version, msgFault, faultException.Action);
}
/// <summary>
/// Enables error-related processing and returns a value that indicates whether the dispatcher aborts the session and the instance context in certain cases.
/// </summary>
/// <param name="error">The exception thrown during processing.</param>
/// <returns>true if Windows Communication Foundation (WCF) should not abort the session (if there is one) and instance context if the instance context is not Single; otherwise, false. The default is false.</returns>
public bool HandleError(Exception error)
{
// could use some logger like Nlog but as an example it will do.
Console.WriteLine("Error occured. {0}", error);
return true;
}
}
在这两种情况下,序列化错误都是:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="sk-SK">My exception</faultstring>
<detail>
<BusinessRuleFaultExceptionType xmlns="http://someurl.temp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Code xmlns="http://namespaces2.url">-100</Code>
<Reason xmlns="http://namespaces2.url">xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>