我可以将消息错误从路由服务返回到 WCF 客户端吗
Can I throw a message fault back to a WCF client from a routing service
我公司长期以来一直通过路由程序使用 ASPX 和 windows 服务来管理连接,并允许我们的数据中心控制客户端建立连接的位置。
最近我们开始使用 MVC 和 WCF。是的,2015 年我们只是转向这些事情。无论如何,他们在发布前大约一个月发现他们需要路由 WCF 流量,因为它位于防火墙之外或 DMZ 中。
我们将把路由服务放在网络中,并在防火墙上打开一个端口,这样所有服务都可以在路由服务的防火墙保护下进行通信。
我提供所有这些详细信息的唯一原因是因为这为我们的 WCF 服务的配置方式设定了预期。我们正在使用证书进行安全和消息加密,因为我们必须发送加密的消息。我们还添加了一个自定义 header,我们的路由器将使用它来路由消息。
我们的工作是我们的路由器接收消息,检查 header,发现我们是否有端点,转发消息,获取响应并将其发送回 WCF 服务。目前,这一切都运行良好。我们甚至可以从端点接收消息故障并将其发送回客户端。
我正在努力解决的问题是,当故障源自路由器时,路由器如何将 messageFault 发送回客户端。但是因为我的路由器不知道如何加密消息,所以这个故障被发回未加密。故障是 "endpoint unreachable" 或 "no endpoint found" 之类的东西。客户端收到这些故障并显示错误:
An unsecured or incorrectly secured fault was received from the other party.
See the inner FaultException for the fault code and detail.
内部异常是我在下面的代码中定义的。
Dim fe As FaultException = New FaultException(status)
Dim fault As MessageFault = fe.CreateMessageFault()
Dim msg = System.ServiceModel.Channels.Message.CreateMessage(getMessageVersion, fault, getAction)
getMessageVersion 将 return Soap11 或 Soap12 取决于客户端
getAction 正在 returning 来自 header.
中客户端请求的操作
有没有办法配置客户端接受这些错误,即使它们没有加密?我们希望将它们捕获为故障异常而不是异常,以便将我们的故障异常逻辑集中在一起用于一般故障。
如有任何帮助或见解,我们将不胜感激。我们的新程序正在使用 C#,我们的旧程序仍然是用 VB 编写的,所以请将您熟悉的任何 .Net 代码扔给我,我会使用它。
这里是故障 class:
[Serializable]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "yourNamespace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "yourNamespace")]
[System.Runtime.Serialization.DataContractAttribute(Namespace = "yourNamespace")]
public class CustomFault : ISerializable
{
public string Message { get; set; }
}
引用故障的界面和操作方法如下:
[ServiceContract(Namespace = "yourNamespace")]
public interface IService
{
[FaultContractAttribute(
typeof(CustomFault),
Action = "",
Name = "Fault",
Namespace = "yourNamespace")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[OperationContract]
Response Operation(Request request);
}
最后是我是如何抛出错误的:
throw new FaultException<CustomFault>
(
new GuiaMedicoFault("Custom Error description"),
new FaultReason("Error description")
);
也许这段代码的某些部分可以帮助您或提供任何想法。
使用 Ricardo 的信息,我能够缩小我正在做的事情。对此的实际答案完全取决于 Endpoint 配置。这取决于您的绑定。
我们不需要更改路由器中的任何东西,但我们必须更改客户端,它看起来像这样。
serviceClient.Endpoint.Binding = getWSHttpBinding();
那么应该是
private CustomBinding getWSHttpBinding()
{
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.MaxReceivedMessageSize = (1024 * 1024 * 10);
BindingElementCollection elements = binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
return new CustomBinding(elements);
}
如果您看到此问题,link 会提供更多信息。 https://support.microsoft.com/en-us/kb/971493
我们可能会将此作为异常处理,而不是故障处理。
我公司长期以来一直通过路由程序使用 ASPX 和 windows 服务来管理连接,并允许我们的数据中心控制客户端建立连接的位置。
最近我们开始使用 MVC 和 WCF。是的,2015 年我们只是转向这些事情。无论如何,他们在发布前大约一个月发现他们需要路由 WCF 流量,因为它位于防火墙之外或 DMZ 中。
我们将把路由服务放在网络中,并在防火墙上打开一个端口,这样所有服务都可以在路由服务的防火墙保护下进行通信。
我提供所有这些详细信息的唯一原因是因为这为我们的 WCF 服务的配置方式设定了预期。我们正在使用证书进行安全和消息加密,因为我们必须发送加密的消息。我们还添加了一个自定义 header,我们的路由器将使用它来路由消息。
我们的工作是我们的路由器接收消息,检查 header,发现我们是否有端点,转发消息,获取响应并将其发送回 WCF 服务。目前,这一切都运行良好。我们甚至可以从端点接收消息故障并将其发送回客户端。
我正在努力解决的问题是,当故障源自路由器时,路由器如何将 messageFault 发送回客户端。但是因为我的路由器不知道如何加密消息,所以这个故障被发回未加密。故障是 "endpoint unreachable" 或 "no endpoint found" 之类的东西。客户端收到这些故障并显示错误:
An unsecured or incorrectly secured fault was received from the other party.
See the inner FaultException for the fault code and detail.
内部异常是我在下面的代码中定义的。
Dim fe As FaultException = New FaultException(status)
Dim fault As MessageFault = fe.CreateMessageFault()
Dim msg = System.ServiceModel.Channels.Message.CreateMessage(getMessageVersion, fault, getAction)
getMessageVersion 将 return Soap11 或 Soap12 取决于客户端 getAction 正在 returning 来自 header.
中客户端请求的操作有没有办法配置客户端接受这些错误,即使它们没有加密?我们希望将它们捕获为故障异常而不是异常,以便将我们的故障异常逻辑集中在一起用于一般故障。
如有任何帮助或见解,我们将不胜感激。我们的新程序正在使用 C#,我们的旧程序仍然是用 VB 编写的,所以请将您熟悉的任何 .Net 代码扔给我,我会使用它。
这里是故障 class:
[Serializable]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "yourNamespace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "yourNamespace")]
[System.Runtime.Serialization.DataContractAttribute(Namespace = "yourNamespace")]
public class CustomFault : ISerializable
{
public string Message { get; set; }
}
引用故障的界面和操作方法如下:
[ServiceContract(Namespace = "yourNamespace")]
public interface IService
{
[FaultContractAttribute(
typeof(CustomFault),
Action = "",
Name = "Fault",
Namespace = "yourNamespace")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[OperationContract]
Response Operation(Request request);
}
最后是我是如何抛出错误的:
throw new FaultException<CustomFault>
(
new GuiaMedicoFault("Custom Error description"),
new FaultReason("Error description")
);
也许这段代码的某些部分可以帮助您或提供任何想法。
使用 Ricardo 的信息,我能够缩小我正在做的事情。对此的实际答案完全取决于 Endpoint 配置。这取决于您的绑定。
我们不需要更改路由器中的任何东西,但我们必须更改客户端,它看起来像这样。
serviceClient.Endpoint.Binding = getWSHttpBinding();
那么应该是
private CustomBinding getWSHttpBinding()
{
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.MaxReceivedMessageSize = (1024 * 1024 * 10);
BindingElementCollection elements = binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
return new CustomBinding(elements);
}
如果您看到此问题,link 会提供更多信息。 https://support.microsoft.com/en-us/kb/971493
我们可能会将此作为异常处理,而不是故障处理。