提问人:Vincent 提问时间:9/16/2019 最后编辑:Vincent 更新时间:9/20/2019 访问量:609
如何使用自定义的 Soap 标头和正文引发 WCF 异常
How to Throw WCF Exception with Customized Soap Header and Body
问:
- 我知道如何使用 [FaultException] 并在 WCF 中抛出自定义的 [DataContract]
- 我知道如何使用 [MessageContract] 返回带有自定义标头和正文标签的 soap 消息
但是,我要问:如何在具有自定义标头和正文的 WCF 中抛出 [FaultException]?因为当我使用 [FaultException] 抛出 [MessageContract] 时,它总是将我的标头和正文标签包装到 body 标签中。
这不是我想要的。大多数 SOAP 客户端不了解 WCF [FaultException]。
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="en-CH" />
<detail>
<CustomizedError xmlns="http://schemas.datacontract.org/2004/07/PlayWcfFault" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<BodyTag1>Hello BodyTag1</BodyTag1>
<HeaderTag1>Hello HeaderTag1</HeaderTag1>
</CustomizedError>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
[MessageContract]
public class CustomizedError
{
[MessageHeader] public string HeaderTag1;
[MessageBodyMember] public string BodyTag1;
}
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(CustomizedError))]
CustomizedError GetData();
}
public class Service1 : IService1
{
public CustomizedError GetData()
{
CustomizedError fault = new CustomizedError
{
HeaderTag1 = "Hello HeaderTag1",
BodyTag1 = "Hello BodyTag1",
};
throw new FaultException<CustomizedError>(fault, "");
// return fault;
}
}
我想要的肥皂消息是
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<HeaderTag1>Hello HeaderTag1</HeaderTag1>
</s:Header >
<s:Body>
<s:Fault>
<BodyTag1>Hello BodyTag1</BodyTag1>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
答:
1赞
Abraham Qian
9/16/2019
#1
我很困惑为什么你以这种格式定义肥皂消息结构。但据我所知,IErrorHandler 接口能够在捕获通信错误时自定义错误消息。下面是一个示例,用于捕获通信过程中的错误。
我们可以在 ProvideFault 方法中添加自定义消息标头。请考虑以下代码。
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, error.Message);
MessageHeader mh = MessageHeader.CreateHeader("itemname", "apptest", "34");
fault.Headers.Add(mh);
}
如果有什么我可以帮忙的,请随时告诉我。
更新。
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:4386");
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.None;
using (ServiceHost sh = new ServiceHost(typeof(TestService), uri))
{
sh.AddServiceEndpoint(typeof(ITestService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true
};
sh.Description.Behaviors.Add(smb);
}
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
sh.Opened += delegate
{
Console.WriteLine("service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("service is closed");
};
sh.Open();
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
public interface ITestService
{
[OperationContract]
int Div(int x, int y);
}
[ServiceBehavior]
public class TestService : ITestService
{
public int Div(int x, int y)
{
if (y == 0)
{
FaultReason reason = new FaultReason("The divisor cannot be Zero");
FaultCode code = new FaultCode("NotZero", "mynamespace",new FaultCode("mysubcode"));
throw new FaultException(reason,code);
}
return x / y;
}
}
为了创建 ActivityID 字段,我们应该在服务器端启用跟踪和消息日志记录。
<system.diagnostics>
<sources>
<source name="System.ServiceModel" propagateActivity="true" switchValue="Information, ActivityTracing">
<listeners>
<add type="System.Diagnostics.XmlWriterTraceListener" name="xmlLog" initializeData="myLogs.svclog"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false"/>
</diagnostics>
</system.serviceModel>
链接。
关于 ActivityID 字段
配置跟踪和消息日志记录
当客户端上的调用传递参数 0 时。我们使用 fiddler 捕获 http 请求。
评论
0赞
Vincent
9/19/2019
谢谢亚伯拉罕·钱。非常接近要求!我需要一个能够抛出这种格式的肥皂的 WCF 应用程序:learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wstep/...
0赞
Abraham Qian
9/20/2019
这可以通过使用使用 wshttpbinding 创建的 WCF 服务来实现。然后我们抛出一个自定义的 Faultexception。请参阅我更新的回复。
评论