e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
256 lines
11 KiB
C#
256 lines
11 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Channels
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.ServiceModel.Description;
|
|
using System.Xml;
|
|
using System.Xml.Schema;
|
|
using System.Web.Services.Description;
|
|
|
|
public class MessageEncodingBindingElementImporter : IWsdlImportExtension, IPolicyImportExtension
|
|
{
|
|
|
|
void IWsdlImportExtension.BeforeImport(ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, ICollection<XmlElement> policy)
|
|
{
|
|
}
|
|
|
|
void IWsdlImportExtension.ImportContract(WsdlImporter importer, WsdlContractConversionContext context) { }
|
|
void IWsdlImportExtension.ImportEndpoint(WsdlImporter importer, WsdlEndpointConversionContext context)
|
|
{
|
|
if (context == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
|
|
}
|
|
|
|
#pragma warning suppress 56506 // [....], these properties cannot be null in this context
|
|
if (context.Endpoint.Binding == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context.Endpoint.Binding");
|
|
}
|
|
|
|
BindingElementCollection bindingElements = GetBindingElements(context);
|
|
MessageEncodingBindingElement messageEncodingBindingElement = bindingElements.Find<MessageEncodingBindingElement>();
|
|
TextMessageEncodingBindingElement textEncodingBindingElement = messageEncodingBindingElement as TextMessageEncodingBindingElement;
|
|
|
|
if (messageEncodingBindingElement != null)
|
|
{
|
|
Type elementType = messageEncodingBindingElement.GetType();
|
|
if (elementType != typeof(TextMessageEncodingBindingElement)
|
|
&& elementType != typeof(BinaryMessageEncodingBindingElement)
|
|
&& elementType != typeof(MtomMessageEncodingBindingElement))
|
|
return;
|
|
}
|
|
|
|
EnsureMessageEncoding(context, messageEncodingBindingElement);
|
|
|
|
foreach (OperationBinding wsdlOperationBinding in context.WsdlBinding.Operations)
|
|
{
|
|
OperationDescription operation = context.GetOperationDescription(wsdlOperationBinding);
|
|
|
|
for (int i = 0; i < operation.Messages.Count; i++)
|
|
{
|
|
MessageDescription message = operation.Messages[i];
|
|
MessageBinding wsdlMessageBinding = context.GetMessageBinding(message);
|
|
ImportMessageSoapAction(context.ContractConversionContext, message, wsdlMessageBinding, i != 0 /*isResponse*/);
|
|
}
|
|
|
|
foreach (FaultDescription fault in operation.Faults)
|
|
{
|
|
FaultBinding wsdlFaultBinding = context.GetFaultBinding(fault);
|
|
if (wsdlFaultBinding != null)
|
|
{
|
|
ImportFaultSoapAction(context.ContractConversionContext, fault, wsdlFaultBinding);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void ImportFaultSoapAction(WsdlContractConversionContext contractContext, FaultDescription fault, FaultBinding wsdlFaultBinding)
|
|
{
|
|
string soapAction = SoapHelper.ReadSoapAction(wsdlFaultBinding.OperationBinding);
|
|
|
|
if (contractContext != null)
|
|
{
|
|
OperationFault wsdlOperationFault = contractContext.GetOperationFault(fault);
|
|
string wsaAction = WsdlImporter.WSAddressingHelper.FindWsaActionAttribute(wsdlOperationFault);
|
|
if (wsaAction == null && soapAction != null)
|
|
fault.Action = soapAction;
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
}
|
|
}
|
|
|
|
static void ImportMessageSoapAction(WsdlContractConversionContext contractContext, MessageDescription message, MessageBinding wsdlMessageBinding, bool isResponse)
|
|
{
|
|
string soapAction = SoapHelper.ReadSoapAction(wsdlMessageBinding.OperationBinding);
|
|
|
|
if (contractContext != null)
|
|
{
|
|
OperationMessage wsdlOperationMessage = contractContext.GetOperationMessage(message);
|
|
string wsaAction = WsdlImporter.WSAddressingHelper.FindWsaActionAttribute(wsdlOperationMessage);
|
|
if (wsaAction == null && soapAction != null)
|
|
{
|
|
if (isResponse)
|
|
{
|
|
message.Action = "*";
|
|
}
|
|
else
|
|
{
|
|
message.Action = soapAction;
|
|
}
|
|
}
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
}
|
|
}
|
|
|
|
static void EnsureMessageEncoding(WsdlEndpointConversionContext context, MessageEncodingBindingElement encodingBindingElement)
|
|
{
|
|
EnvelopeVersion soapVersion = SoapHelper.GetSoapVersion(context.WsdlBinding);
|
|
AddressingVersion addressingVersion;
|
|
|
|
if (encodingBindingElement == null)
|
|
{
|
|
encodingBindingElement = new TextMessageEncodingBindingElement();
|
|
ConvertToCustomBinding(context).Elements.Add(encodingBindingElement);
|
|
|
|
addressingVersion = AddressingVersion.None;
|
|
}
|
|
else
|
|
{
|
|
if (soapVersion == EnvelopeVersion.None)
|
|
addressingVersion = AddressingVersion.None;
|
|
else
|
|
addressingVersion = encodingBindingElement.MessageVersion.Addressing;
|
|
}
|
|
|
|
MessageVersion newMessageVersion = MessageVersion.CreateVersion(soapVersion, addressingVersion);
|
|
if (!encodingBindingElement.MessageVersion.IsMatch(newMessageVersion))
|
|
{
|
|
ConvertToCustomBinding(context).Elements.Find<MessageEncodingBindingElement>().MessageVersion
|
|
= MessageVersion.CreateVersion(soapVersion, addressingVersion);
|
|
}
|
|
}
|
|
|
|
static BindingElementCollection GetBindingElements(WsdlEndpointConversionContext context)
|
|
{
|
|
Binding binding = context.Endpoint.Binding;
|
|
BindingElementCollection elements = binding is CustomBinding ? ((CustomBinding)binding).Elements : binding.CreateBindingElements();
|
|
return elements;
|
|
}
|
|
|
|
static CustomBinding ConvertToCustomBinding(WsdlEndpointConversionContext context)
|
|
{
|
|
CustomBinding customBinding = context.Endpoint.Binding as CustomBinding;
|
|
if (customBinding == null)
|
|
{
|
|
customBinding = new CustomBinding(context.Endpoint.Binding);
|
|
context.Endpoint.Binding = customBinding;
|
|
}
|
|
return customBinding;
|
|
}
|
|
|
|
|
|
void IPolicyImportExtension.ImportPolicy(MetadataImporter importer, PolicyConversionContext context)
|
|
{
|
|
if (importer == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("importer");
|
|
}
|
|
|
|
if (context == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
|
|
}
|
|
|
|
ImportPolicyInternal(context);
|
|
}
|
|
|
|
void ImportPolicyInternal(PolicyConversionContext context)
|
|
{
|
|
ICollection<XmlElement> assertions = context.GetBindingAssertions();
|
|
|
|
XmlElement encodingAssertion;
|
|
MessageEncodingBindingElement encodingBindingElement;
|
|
encodingBindingElement = CreateEncodingBindingElement(context.GetBindingAssertions(), out encodingAssertion);
|
|
|
|
AddressingVersion addressingVersion = WsdlImporter.WSAddressingHelper.FindAddressingVersion(context);
|
|
ApplyAddressingVersion(encodingBindingElement, addressingVersion);
|
|
|
|
|
|
#pragma warning suppress 56506
|
|
context.BindingElements.Add(encodingBindingElement);
|
|
}
|
|
|
|
static void ApplyAddressingVersion(MessageEncodingBindingElement encodingBindingElement, AddressingVersion addressingVersion)
|
|
{
|
|
EnvelopeVersion defaultEnvelopeVersion = encodingBindingElement.MessageVersion.Envelope;
|
|
|
|
if (defaultEnvelopeVersion == EnvelopeVersion.None
|
|
&& addressingVersion != AddressingVersion.None)
|
|
{
|
|
// The default envelope version is None which incompatible with the
|
|
// addressing version.
|
|
// We replace it with soap12. This will be updated at wsdl import time if necessary.
|
|
encodingBindingElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, addressingVersion);
|
|
}
|
|
else
|
|
{
|
|
encodingBindingElement.MessageVersion = MessageVersion.CreateVersion(defaultEnvelopeVersion, addressingVersion);
|
|
}
|
|
}
|
|
|
|
MessageEncodingBindingElement CreateEncodingBindingElement(ICollection<XmlElement> assertions, out XmlElement encodingAssertion)
|
|
{
|
|
encodingAssertion = null;
|
|
foreach (XmlElement assertion in assertions)
|
|
{
|
|
switch (assertion.NamespaceURI)
|
|
{
|
|
case MessageEncodingPolicyConstants.BinaryEncodingNamespace:
|
|
if (assertion.LocalName == MessageEncodingPolicyConstants.BinaryEncodingName)
|
|
{
|
|
encodingAssertion = assertion;
|
|
assertions.Remove(encodingAssertion);
|
|
return new BinaryMessageEncodingBindingElement();
|
|
}
|
|
break;
|
|
case MessageEncodingPolicyConstants.OptimizedMimeSerializationNamespace:
|
|
if (assertion.LocalName == MessageEncodingPolicyConstants.MtomEncodingName)
|
|
{
|
|
encodingAssertion = assertion;
|
|
assertions.Remove(encodingAssertion);
|
|
return new MtomMessageEncodingBindingElement();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return new TextMessageEncodingBindingElement();
|
|
}
|
|
}
|
|
|
|
static class MessageEncodingPolicyConstants
|
|
{
|
|
public const string BinaryEncodingName = "BinaryEncoding";
|
|
public const string BinaryEncodingNamespace = "http://schemas.microsoft.com/ws/06/2004/mspolicy/netbinary1";
|
|
public const string BinaryEncodingPrefix = "msb";
|
|
public const string OptimizedMimeSerializationNamespace = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization";
|
|
public const string OptimizedMimeSerializationPrefix = "wsoma";
|
|
public const string MtomEncodingName = "OptimizedMimeSerialization";
|
|
}
|
|
}
|
|
|