我有一组在.NET 4.6中编码的工作WCF Web服务 - 它们正在向服务器进行出站调用。因此,它们运行在.EXE中(实际上最终将作为Windows服务运行)。
这些Web服务需要支持WS-Addressing标准:
W3C Web服务寻址1.0 - 核心http://www.w3.org/TR/2006/REC-ws-addr-core-20060509
该版本的标准声明WSA:TO元素是可选的。我需要的是WSA:TO元素根本不出现在SOAP输出中。我想这样做而不必编写自定义SOAP编写器,因为我还需要使用WS-SECURITY。我用Google搜索等等
在我的绑定配置中,我有:
<binding name="MyServiceThatMustNotSendWSATO">
<textMessageEncoding messageVersion="Soap12WSAddressing10" />
<httpTransport />
</binding>
终点是:
<endpoint address="http://destinationserver.com/SomeServiceName/V1"
behaviorConfiguration="cliBeh" binding="customBinding" bindingConfiguration="MyServiceThatMustNotSendWSATO"
contract="SomeContract.SomeMethod" name="SomeEndPointName">
<identity>
<dns value="somedns" />
</identity>
</endpoint>
我已经尝试了textMessageEncoding messageVersion的所有组合,但仍然生成了WSA:TO元素:(
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">tns:ServiceEntryStatusOut_V1</a:Action>
<a:MessageID>urn:uuid:88eda3c6-2b6a-4672-8e96-28f0e91c8b4c</a:MessageID>
<a:RelatesTo>urn:uuid:1f19a9f3-6e46-47cc-b190-cc7ef71dbc67</a:RelatesTo>
<a:To s:mustUnderstand="1">http://www.com/</a:To>
</s:Header>
所以在一个坚果shell中,我需要WS-Address字段,如Action,Message ID,RelatesTo,但不是To元素。
你有过这样的项目吗?好吧,这个问题是我面临的一些噩梦般问题的一部分。但最后,我克服了所有这些并得到了一个有效的解决方案。这不是一个好的解决方案,但它永远不会如此。
无论如何,要解决这个特殊问题,我必须使用自定义ClientMessageInspector类来删除有问题的字段。该类是自定义行为扩展的一部分。在我的问题中,我说我不想这样做 - 在我的研究中,这根本不可能。您确实需要自定义类来覆盖默认的.NET SOAP处理类。
我的自定义检查器代码最终如下:
internal class ClientMessageInspector : IEndpointBehavior, IClientMessageInspector
{
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
//throw new Exception("Exception in ApplyDispatchBehavior : ");
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
//throw new Exception("Exception in ApplyClientBehavior : ");
clientRuntime.ClientMessageInspectors.Add(this);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
//throw new Exception("Exception in BeforeSendRequest : " + request.Headers.MessageId);
var message = request;
request = new MyCustomMessage(message);
return null;
}
public class MyCustomMessage : Message
{
private readonly Message _message;
public MyCustomMessage(Message message)
{
this._message = message;
}
protected override void OnWriteBodyContents(System.Xml.XmlDictionaryWriter writer)
{
MethodInfo dynMethod = _message.GetType().GetMethod("OnWriteBodyContents", BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(_message, new object[] { writer });
}
public override MessageHeaders Headers
{
get
{
// Remove wsa:To header
var index = this._message.Headers.FindHeader("To", "http://www.w3.org/2005/08/addressing");
if (index > 0)
{
this._message.Headers.RemoveAt(index);
}
// Remove wsa:ReplyTo header
index = this._message.Headers.FindHeader("ReplyTo", "http://www.w3.org/2005/08/addressing");
if (index > 0)
{
this._message.Headers.RemoveAt(index);
}
// Remove VsDebuggerCausalityData (only appears in Dev but here from convenience)
index = this._message.Headers.FindHeader("VsDebuggerCausalityData", "http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink");
if (index > 0)
{
this._message.Headers.RemoveAt(index);
}
return this._message.Headers;
}
}
public override MessageProperties Properties
{
get { return this._message.Properties; }
}
public override MessageVersion Version
{
get { return this._message.Version; }
}
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
//throw new Exception("Exception in AfterReceiveReply : ");
}
}
所需的绑定很复杂,但最终结果如下。关键是使用自定义行为扩展来执行繁重的工作来删除这些字段。
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="myBehaviorExtensionElement"
type="MySecurityBE.MyBehaviorExtensionElement, MySecurityBE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<bindings>
<customBinding>
<binding name="ServiceName_soap12" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" useDefaultWebProxy="true" allowCookies="false">
<textMessageEncoding messageVersion="Soap12WSAddressing10" />
<httpTransport maxReceivedMessageSize="2147483647" />
</binding>
</customBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="cliBeh">
<myBehaviorExtensionElement/>
<clientCredentials>
<clientCertificate storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" findValue="BradTestClientKey"/>
<serviceCertificate>
<defaultCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" findValue="localhost2"/>
<authentication certificateValidationMode="None" trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost.fiddler/TestRigClient_WS/Services/MyService"
binding="customBinding" bindingConfiguration="ServiceName_soap12"
contract="GenericFileTransferService.GenericFileTransfer"
name="ServiceName_soap12" behaviorConfiguration="cliBeh">
<identity>
<dns value="localhost2"/>
</identity>
</endpoint>
</client>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" maxMessagesToLog="30000000" maxSizeOfMessageToLog="2000000"/>
</diagnostics>
</system.serviceModel>
我希望任何人都面对同样的战斗,祝你好运。漫长的REST和可能SOAP死了一个非常安静的死亡,它是如此丰富的应得(只是我在该项目上度过的噩梦之后的意见)。