e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
1281 lines
58 KiB
C#
1281 lines
58 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Description
|
|
{
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Runtime;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Channels;
|
|
using System.Xml;
|
|
using System.Xml.Schema;
|
|
using System.Xml.Serialization;
|
|
using WsdlNS = System.Web.Services.Description;
|
|
|
|
public class WsdlExporter : MetadataExporter
|
|
{
|
|
static XmlDocument xmlDocument;
|
|
bool isFaulted = false;
|
|
|
|
|
|
WsdlNS.ServiceDescriptionCollection wsdlDocuments = new WsdlNS.ServiceDescriptionCollection();
|
|
XmlSchemaSet xmlSchemas = WsdlExporter.GetEmptySchemaSet();
|
|
|
|
Dictionary<ContractDescription, WsdlContractConversionContext> exportedContracts
|
|
= new Dictionary<ContractDescription, WsdlContractConversionContext>();
|
|
Dictionary<BindingDictionaryKey, WsdlEndpointConversionContext> exportedBindings = new Dictionary<BindingDictionaryKey, WsdlEndpointConversionContext>();
|
|
Dictionary<EndpointDictionaryKey, ServiceEndpoint> exportedEndpoints = new Dictionary<EndpointDictionaryKey, ServiceEndpoint>();
|
|
|
|
public override void ExportContract(ContractDescription contract)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlExporterIsFaulted)));
|
|
|
|
if (contract == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
|
|
|
|
if (!this.exportedContracts.ContainsKey(contract))
|
|
{
|
|
try
|
|
{
|
|
WsdlNS.PortType wsdlPortType = CreateWsdlPortType(contract);
|
|
WsdlContractConversionContext contractContext;
|
|
|
|
|
|
contractContext = new WsdlContractConversionContext(contract, wsdlPortType);
|
|
|
|
foreach (OperationDescription operation in contract.Operations)
|
|
{
|
|
bool isWildcardAction;
|
|
if (!OperationIsExportable(operation, out isWildcardAction))
|
|
{
|
|
string warningMsg = isWildcardAction ? SR.GetString(SR.WarnSkippingOpertationWithWildcardAction, contract.Name, contract.Namespace, operation.Name)
|
|
: SR.GetString(SR.WarnSkippingOpertationWithSessionOpenNotificationEnabled, "Action", OperationDescription.SessionOpenedAction, contract.Name, contract.Namespace, operation.Name);
|
|
|
|
LogExportWarning(warningMsg);
|
|
continue;
|
|
}
|
|
|
|
WsdlNS.Operation wsdlOperation = CreateWsdlOperation(operation, contract);
|
|
wsdlPortType.Operations.Add(wsdlOperation);
|
|
|
|
contractContext.AddOperation(operation, wsdlOperation);
|
|
|
|
foreach (MessageDescription message in operation.Messages)
|
|
{
|
|
//Create Operation Message
|
|
WsdlNS.OperationMessage wsdlOperationMessage = CreateWsdlOperationMessage(message);
|
|
wsdlOperation.Messages.Add(wsdlOperationMessage);
|
|
contractContext.AddMessage(message, wsdlOperationMessage);
|
|
}
|
|
|
|
foreach (FaultDescription fault in operation.Faults)
|
|
{
|
|
//Create Operation Fault
|
|
WsdlNS.OperationFault wsdlOperationFault = CreateWsdlOperationFault(fault);
|
|
wsdlOperation.Faults.Add(wsdlOperationFault);
|
|
contractContext.AddFault(fault, wsdlOperationFault);
|
|
}
|
|
}
|
|
|
|
CallExportContract(contractContext);
|
|
|
|
exportedContracts.Add(contract, contractContext);
|
|
}
|
|
catch
|
|
{
|
|
isFaulted = true;
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void ExportEndpoint(ServiceEndpoint endpoint)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlExporterIsFaulted)));
|
|
|
|
if (endpoint == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
|
|
|
|
ExportEndpoint(endpoint, new XmlQualifiedName(NamingHelper.DefaultServiceName, NamingHelper.DefaultNamespace), null);
|
|
}
|
|
|
|
public void ExportEndpoints(IEnumerable<ServiceEndpoint> endpoints, XmlQualifiedName wsdlServiceQName)
|
|
{
|
|
this.ExportEndpoints(endpoints, wsdlServiceQName, null);
|
|
}
|
|
|
|
internal void ExportEndpoints(IEnumerable<ServiceEndpoint> endpoints, XmlQualifiedName wsdlServiceQName, BindingParameterCollection bindingParameters)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlExporterIsFaulted)));
|
|
|
|
if (endpoints == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoints");
|
|
if (wsdlServiceQName == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlServiceQName");
|
|
|
|
foreach (ServiceEndpoint endpoint in endpoints)
|
|
{
|
|
ExportEndpoint(endpoint, wsdlServiceQName, bindingParameters);
|
|
}
|
|
}
|
|
|
|
public override MetadataSet GetGeneratedMetadata()
|
|
{
|
|
MetadataSet set = new MetadataSet();
|
|
|
|
foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
|
|
set.MetadataSections.Add(MetadataSection.CreateFromServiceDescription(wsdl));
|
|
|
|
foreach (XmlSchema schema in xmlSchemas.Schemas())
|
|
set.MetadataSections.Add(MetadataSection.CreateFromSchema(schema));
|
|
|
|
return set;
|
|
}
|
|
|
|
public WsdlNS.ServiceDescriptionCollection GeneratedWsdlDocuments { get { return wsdlDocuments; } }
|
|
public XmlSchemaSet GeneratedXmlSchemas { get { return xmlSchemas; } }
|
|
|
|
void ExportEndpoint(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, BindingParameterCollection bindingParameters)
|
|
{
|
|
if (endpoint.Binding == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.EndpointsMustHaveAValidBinding1, endpoint.Name)));
|
|
|
|
EndpointDictionaryKey endpointKey = new EndpointDictionaryKey(endpoint, wsdlServiceQName);
|
|
|
|
try
|
|
{
|
|
if (exportedEndpoints.ContainsKey(endpointKey))
|
|
return;
|
|
|
|
this.ExportContract(endpoint.Contract);
|
|
|
|
// Retreive Conversion Context for Contract;
|
|
// Note: Contract must have already been exported at this point.
|
|
WsdlContractConversionContext contractContext = this.exportedContracts[endpoint.Contract];
|
|
|
|
|
|
bool newWsdlBinding, bindingNameWasUniquified;
|
|
WsdlNS.Port wsdlPort;
|
|
WsdlNS.Binding wsdlBinding;
|
|
wsdlBinding = CreateWsdlBindingAndPort(endpoint, wsdlServiceQName, out wsdlPort, out newWsdlBinding, out bindingNameWasUniquified);
|
|
|
|
|
|
if (!newWsdlBinding && wsdlPort == null)
|
|
return;
|
|
|
|
// Create an Endpoint conversion context based on
|
|
// the contract's conversion context (reuse contract correlation information)
|
|
WsdlEndpointConversionContext endpointContext;
|
|
if (newWsdlBinding)
|
|
{
|
|
endpointContext = new WsdlEndpointConversionContext(contractContext, endpoint, wsdlBinding, wsdlPort);
|
|
|
|
foreach (OperationDescription operation in endpoint.Contract.Operations)
|
|
{
|
|
if (!WsdlExporter.OperationIsExportable(operation))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
WsdlNS.OperationBinding wsdlOperationBinding = CreateWsdlOperationBinding(endpoint.Contract, operation);
|
|
wsdlBinding.Operations.Add(wsdlOperationBinding);
|
|
|
|
endpointContext.AddOperationBinding(operation, wsdlOperationBinding);
|
|
|
|
foreach (MessageDescription message in operation.Messages)
|
|
{
|
|
WsdlNS.MessageBinding wsdlMessageBinding = CreateWsdlMessageBinding(message, endpoint.Binding, wsdlOperationBinding);
|
|
endpointContext.AddMessageBinding(message, wsdlMessageBinding);
|
|
}
|
|
|
|
foreach (FaultDescription fault in operation.Faults)
|
|
{
|
|
WsdlNS.FaultBinding wsdlFaultBinding = CreateWsdlFaultBinding(fault, endpoint.Binding, wsdlOperationBinding);
|
|
endpointContext.AddFaultBinding(fault, wsdlFaultBinding);
|
|
}
|
|
}
|
|
|
|
// CSDMain 180381: Added internal functionality for passing BindingParameters into the ExportPolicy process via PolicyConversionContext.
|
|
// However, in order to not change existing behavior, we only call the internal ExportPolicy method which accepts BindingParameters if they are not null
|
|
// (non-null binding parameters can only be passed in via internal code paths). Otherwise, we call the existing ExportPolicy method, just like before.
|
|
PolicyConversionContext policyContext;
|
|
if (bindingParameters == null)
|
|
{
|
|
policyContext = this.ExportPolicy(endpoint);
|
|
}
|
|
else
|
|
{
|
|
policyContext = this.ExportPolicy(endpoint, bindingParameters);
|
|
}
|
|
// consider factoring this out of wsdl exporter
|
|
new WSPolicyAttachmentHelper(this.PolicyVersion).AttachPolicy(endpoint, endpointContext, policyContext);
|
|
exportedBindings.Add(new BindingDictionaryKey(endpoint.Contract, endpoint.Binding), endpointContext);
|
|
}
|
|
else
|
|
{
|
|
endpointContext = new WsdlEndpointConversionContext(exportedBindings[new BindingDictionaryKey(endpoint.Contract, endpoint.Binding)], endpoint, wsdlPort);
|
|
}
|
|
|
|
CallExportEndpoint(endpointContext);
|
|
exportedEndpoints.Add(endpointKey, endpoint);
|
|
if (bindingNameWasUniquified)
|
|
Errors.Add(new MetadataConversionError(SR.GetString(SR.WarnDuplicateBindingQNameNameOnExport, endpoint.Binding.Name, endpoint.Binding.Namespace, endpoint.Contract.Name), true /*isWarning*/));
|
|
}
|
|
catch
|
|
{
|
|
isFaulted = true;
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void CallExportEndpoint(WsdlEndpointConversionContext endpointContext)
|
|
{
|
|
foreach (IWsdlExportExtension extension in endpointContext.ExportExtensions)
|
|
{
|
|
CallExtension(endpointContext, extension);
|
|
}
|
|
}
|
|
|
|
void CallExportContract(WsdlContractConversionContext contractContext)
|
|
{
|
|
foreach (IWsdlExportExtension extension in contractContext.ExportExtensions)
|
|
{
|
|
CallExtension(contractContext, extension);
|
|
}
|
|
}
|
|
|
|
WsdlNS.PortType CreateWsdlPortType(ContractDescription contract)
|
|
{
|
|
XmlQualifiedName wsdlPortTypeQName = WsdlNamingHelper.GetPortTypeQName(contract);
|
|
|
|
WsdlNS.ServiceDescription wsdl = GetOrCreateWsdl(wsdlPortTypeQName.Namespace);
|
|
WsdlNS.PortType wsdlPortType = new WsdlNS.PortType();
|
|
wsdlPortType.Name = wsdlPortTypeQName.Name;
|
|
if (wsdl.PortTypes[wsdlPortType.Name] != null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.DuplicateContractQNameNameOnExport, contract.Name, contract.Namespace)));
|
|
NetSessionHelper.AddUsingSessionAttributeIfNeeded(wsdlPortType, contract);
|
|
wsdl.PortTypes.Add(wsdlPortType);
|
|
|
|
return wsdlPortType;
|
|
}
|
|
|
|
WsdlNS.Operation CreateWsdlOperation(OperationDescription operation, ContractDescription contract)
|
|
{
|
|
WsdlNS.Operation wsdlOperation = new WsdlNS.Operation();
|
|
wsdlOperation.Name = WsdlNamingHelper.GetWsdlOperationName(operation, contract);
|
|
NetSessionHelper.AddInitiatingTerminatingAttributesIfNeeded(wsdlOperation, operation, contract);
|
|
return wsdlOperation;
|
|
}
|
|
|
|
WsdlNS.OperationMessage CreateWsdlOperationMessage(MessageDescription message)
|
|
{
|
|
WsdlNS.OperationMessage wsdlOperationMessage;
|
|
|
|
if (message.Direction == MessageDirection.Input)
|
|
wsdlOperationMessage = new WsdlNS.OperationInput();
|
|
else
|
|
wsdlOperationMessage = new WsdlNS.OperationOutput();
|
|
|
|
if (!XmlName.IsNullOrEmpty(message.MessageName))
|
|
wsdlOperationMessage.Name = message.MessageName.EncodedName;
|
|
|
|
// consider factoring this out of wslExporter
|
|
WSAddressingHelper.AddActionAttribute(message.Action, wsdlOperationMessage, this.PolicyVersion);
|
|
return wsdlOperationMessage;
|
|
}
|
|
|
|
WsdlNS.OperationFault CreateWsdlOperationFault(FaultDescription fault)
|
|
{
|
|
WsdlNS.OperationFault wsdlOperationFault;
|
|
wsdlOperationFault = new WsdlNS.OperationFault();
|
|
|
|
// operation fault name must not be empty (FaultDescription checks this)
|
|
wsdlOperationFault.Name = fault.Name;
|
|
|
|
// consider factoring this out of wslExporter
|
|
WSAddressingHelper.AddActionAttribute(fault.Action, wsdlOperationFault, this.PolicyVersion);
|
|
return wsdlOperationFault;
|
|
}
|
|
|
|
WsdlNS.Binding CreateWsdlBindingAndPort(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, out WsdlNS.Port wsdlPort, out bool newBinding, out bool bindingNameWasUniquified)
|
|
{
|
|
WsdlNS.ServiceDescription bindingWsdl;
|
|
WsdlNS.Binding wsdlBinding;
|
|
WsdlEndpointConversionContext bindingConversionContext;
|
|
XmlQualifiedName wsdlBindingQName;
|
|
XmlQualifiedName wsdlPortTypeQName;
|
|
bool printWsdlDeclaration = IsWsdlExportable(endpoint.Binding);
|
|
|
|
if (!exportedBindings.TryGetValue(new BindingDictionaryKey(endpoint.Contract, endpoint.Binding), out bindingConversionContext))
|
|
{
|
|
wsdlBindingQName = WsdlNamingHelper.GetBindingQName(endpoint, this, out bindingNameWasUniquified);
|
|
bindingWsdl = GetOrCreateWsdl(wsdlBindingQName.Namespace);
|
|
wsdlBinding = new WsdlNS.Binding();
|
|
wsdlBinding.Name = wsdlBindingQName.Name;
|
|
newBinding = true;
|
|
|
|
WsdlNS.PortType wsdlPortType = exportedContracts[endpoint.Contract].WsdlPortType;
|
|
wsdlPortTypeQName = new XmlQualifiedName(wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace);
|
|
wsdlBinding.Type = wsdlPortTypeQName;
|
|
if (printWsdlDeclaration)
|
|
{
|
|
bindingWsdl.Bindings.Add(wsdlBinding);
|
|
}
|
|
WsdlExporter.EnsureWsdlContainsImport(bindingWsdl, wsdlPortTypeQName.Namespace);
|
|
}
|
|
else
|
|
{
|
|
wsdlBindingQName = new XmlQualifiedName(bindingConversionContext.WsdlBinding.Name, bindingConversionContext.WsdlBinding.ServiceDescription.TargetNamespace);
|
|
bindingNameWasUniquified = false;
|
|
bindingWsdl = wsdlDocuments[wsdlBindingQName.Namespace];
|
|
wsdlBinding = bindingWsdl.Bindings[wsdlBindingQName.Name];
|
|
wsdlPortTypeQName = wsdlBinding.Type;
|
|
newBinding = false;
|
|
}
|
|
|
|
|
|
//We can only create a Port if there is an address
|
|
if (endpoint.Address != null)
|
|
{
|
|
WsdlNS.Service wsdlService = GetOrCreateWsdlService(wsdlServiceQName);
|
|
|
|
wsdlPort = new WsdlNS.Port();
|
|
string wsdlPortName = WsdlNamingHelper.GetPortName(endpoint, wsdlService);
|
|
wsdlPort.Name = wsdlPortName;
|
|
wsdlPort.Binding = wsdlBindingQName;
|
|
|
|
WsdlNS.SoapAddressBinding addressBinding = SoapHelper.GetOrCreateSoapAddressBinding(wsdlBinding, wsdlPort, this);
|
|
|
|
if (addressBinding != null)
|
|
{
|
|
addressBinding.Location = endpoint.Address.Uri.AbsoluteUri;
|
|
}
|
|
|
|
WsdlExporter.EnsureWsdlContainsImport(wsdlService.ServiceDescription, wsdlBindingQName.Namespace);
|
|
if (printWsdlDeclaration)
|
|
{
|
|
wsdlService.Ports.Add(wsdlPort);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wsdlPort = null;
|
|
}
|
|
|
|
return wsdlBinding;
|
|
}
|
|
|
|
WsdlNS.OperationBinding CreateWsdlOperationBinding(ContractDescription contract, OperationDescription operation)
|
|
{
|
|
WsdlNS.OperationBinding wsdlOperationBinding = new WsdlNS.OperationBinding();
|
|
wsdlOperationBinding.Name = WsdlNamingHelper.GetWsdlOperationName(operation, contract);
|
|
return wsdlOperationBinding;
|
|
}
|
|
|
|
WsdlNS.MessageBinding CreateWsdlMessageBinding(MessageDescription messageDescription, Binding binding, WsdlNS.OperationBinding wsdlOperationBinding)
|
|
{
|
|
WsdlNS.MessageBinding wsdlMessageBinding;
|
|
if (messageDescription.Direction == MessageDirection.Input)
|
|
{
|
|
wsdlOperationBinding.Input = new WsdlNS.InputBinding();
|
|
wsdlMessageBinding = wsdlOperationBinding.Input;
|
|
}
|
|
else
|
|
{
|
|
wsdlOperationBinding.Output = new WsdlNS.OutputBinding();
|
|
wsdlMessageBinding = wsdlOperationBinding.Output;
|
|
}
|
|
|
|
if (!XmlName.IsNullOrEmpty(messageDescription.MessageName))
|
|
wsdlMessageBinding.Name = messageDescription.MessageName.EncodedName;
|
|
|
|
return wsdlMessageBinding;
|
|
}
|
|
|
|
WsdlNS.FaultBinding CreateWsdlFaultBinding(FaultDescription faultDescription, Binding binding, WsdlNS.OperationBinding wsdlOperationBinding)
|
|
{
|
|
WsdlNS.FaultBinding wsdlFaultBinding = new WsdlNS.FaultBinding();
|
|
wsdlOperationBinding.Faults.Add(wsdlFaultBinding);
|
|
if (faultDescription.Name != null)
|
|
wsdlFaultBinding.Name = faultDescription.Name;
|
|
|
|
return wsdlFaultBinding;
|
|
}
|
|
|
|
internal static bool OperationIsExportable(OperationDescription operation)
|
|
{
|
|
bool isWildcardAction;
|
|
return OperationIsExportable(operation, out isWildcardAction);
|
|
}
|
|
|
|
internal static bool OperationIsExportable(OperationDescription operation, out bool isWildcardAction)
|
|
{
|
|
isWildcardAction = false;
|
|
|
|
if (operation.IsSessionOpenNotificationEnabled)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < operation.Messages.Count; i++)
|
|
{
|
|
if (operation.Messages[i].Action == MessageHeaders.WildcardAction)
|
|
{
|
|
isWildcardAction = true;
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal static bool IsBuiltInOperationBehavior(IWsdlExportExtension extension)
|
|
{
|
|
DataContractSerializerOperationBehavior dcsob = extension as DataContractSerializerOperationBehavior;
|
|
if (dcsob != null)
|
|
{
|
|
return dcsob.IsBuiltInOperationBehavior;
|
|
}
|
|
|
|
XmlSerializerOperationBehavior xsob = extension as XmlSerializerOperationBehavior;
|
|
if (xsob != null)
|
|
{
|
|
return xsob.IsBuiltInOperationBehavior;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static XmlDocument XmlDoc
|
|
{
|
|
get
|
|
{
|
|
if (xmlDocument == null)
|
|
{
|
|
NameTable nameTable = new NameTable();
|
|
nameTable.Add(MetadataStrings.WSPolicy.Elements.Policy);
|
|
nameTable.Add(MetadataStrings.WSPolicy.Elements.All);
|
|
nameTable.Add(MetadataStrings.WSPolicy.Elements.ExactlyOne);
|
|
nameTable.Add(MetadataStrings.WSPolicy.Attributes.PolicyURIs);
|
|
nameTable.Add(MetadataStrings.Wsu.Attributes.Id);
|
|
nameTable.Add(MetadataStrings.Addressing200408.Policy.UsingAddressing);
|
|
nameTable.Add(MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing);
|
|
nameTable.Add(MetadataStrings.Addressing10.MetadataPolicy.Addressing);
|
|
nameTable.Add(MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses);
|
|
nameTable.Add(MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses);
|
|
xmlDocument = new XmlDocument(nameTable);
|
|
}
|
|
return xmlDocument;
|
|
}
|
|
}
|
|
|
|
// Generate WSDL Document if it doesn't already exist otherwise, return the appropriate WSDL document
|
|
internal WsdlNS.ServiceDescription GetOrCreateWsdl(string ns)
|
|
{
|
|
// NOTE: this method is not thread safe
|
|
WsdlNS.ServiceDescriptionCollection wsdlCollection = this.wsdlDocuments;
|
|
WsdlNS.ServiceDescription wsdl = wsdlCollection[ns];
|
|
|
|
// Look for wsdl in service descriptions that have been created. If we cannot find it then we create it
|
|
if (wsdl == null)
|
|
{
|
|
wsdl = new WsdlNS.ServiceDescription();
|
|
wsdl.TargetNamespace = ns;
|
|
|
|
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(new WsdlNamespaceHelper(this.PolicyVersion).SerializerNamespaces);
|
|
if (!string.IsNullOrEmpty(wsdl.TargetNamespace))
|
|
namespaces.Add("tns", wsdl.TargetNamespace);
|
|
wsdl.Namespaces = namespaces;
|
|
|
|
wsdlCollection.Add(wsdl);
|
|
}
|
|
|
|
return wsdl;
|
|
}
|
|
|
|
WsdlNS.Service GetOrCreateWsdlService(XmlQualifiedName wsdlServiceQName)
|
|
{
|
|
// NOTE: this method is not thread safe
|
|
|
|
WsdlNS.ServiceDescription wsdl = GetOrCreateWsdl(wsdlServiceQName.Namespace);
|
|
|
|
WsdlNS.Service wsdlService = wsdl.Services[wsdlServiceQName.Name];
|
|
if (wsdlService == null)
|
|
{
|
|
//Service not found. Create service.
|
|
wsdlService = new WsdlNS.Service();
|
|
wsdlService.Name = wsdlServiceQName.Name;
|
|
|
|
if (string.IsNullOrEmpty(wsdl.Name))
|
|
wsdl.Name = wsdlService.Name;
|
|
|
|
wsdl.Services.Add(wsdlService);
|
|
}
|
|
return wsdlService;
|
|
}
|
|
|
|
static void EnsureWsdlContainsImport(WsdlNS.ServiceDescription srcWsdl, string target)
|
|
{
|
|
if (srcWsdl.TargetNamespace == target)
|
|
return;
|
|
// FindImport
|
|
foreach (WsdlNS.Import import in srcWsdl.Imports)
|
|
{
|
|
if (import.Namespace == target)
|
|
return;
|
|
}
|
|
{
|
|
WsdlNS.Import import = new WsdlNS.Import();
|
|
import.Location = null;
|
|
import.Namespace = target;
|
|
srcWsdl.Imports.Add(import);
|
|
WsdlNamespaceHelper.FindOrCreatePrefix("i", target, srcWsdl);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void LogExportWarning(string warningMessage)
|
|
{
|
|
this.Errors.Add(new MetadataConversionError(warningMessage, true));
|
|
}
|
|
|
|
static internal XmlSchemaSet GetEmptySchemaSet()
|
|
{
|
|
XmlSchemaSet schemaSet = new XmlSchemaSet();
|
|
schemaSet.XmlResolver = null;
|
|
return schemaSet;
|
|
}
|
|
|
|
static bool IsWsdlExportable(Binding binding)
|
|
{
|
|
BindingElementCollection bindingElements = binding.CreateBindingElements();
|
|
if (bindingElements == null)
|
|
{
|
|
return true;
|
|
}
|
|
foreach (BindingElement bindingElement in bindingElements)
|
|
{
|
|
MessageEncodingBindingElement messageEncodingBindingElement = bindingElement as MessageEncodingBindingElement;
|
|
if (messageEncodingBindingElement != null && !messageEncodingBindingElement.IsWsdlExportable)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal static class WSAddressingHelper
|
|
{
|
|
internal static void AddActionAttribute(string actionUri, WsdlNS.OperationMessage wsdlOperationMessage, PolicyVersion policyVersion)
|
|
{
|
|
XmlAttribute attribute;
|
|
if (policyVersion == PolicyVersion.Policy12)
|
|
{
|
|
attribute = WsdlExporter.XmlDoc.CreateAttribute(MetadataStrings.AddressingWsdl.Prefix,
|
|
MetadataStrings.AddressingWsdl.Action,
|
|
MetadataStrings.AddressingWsdl.NamespaceUri);
|
|
}
|
|
else
|
|
{
|
|
attribute = WsdlExporter.XmlDoc.CreateAttribute(MetadataStrings.AddressingMetadata.Prefix,
|
|
MetadataStrings.AddressingMetadata.Action,
|
|
MetadataStrings.AddressingMetadata.NamespaceUri);
|
|
}
|
|
|
|
attribute.Value = actionUri;
|
|
wsdlOperationMessage.ExtensibleAttributes = new XmlAttribute[] { attribute };
|
|
}
|
|
|
|
internal static void AddAddressToWsdlPort(WsdlNS.Port wsdlPort, EndpointAddress addr, AddressingVersion addressing)
|
|
{
|
|
if (addressing == AddressingVersion.None)
|
|
{
|
|
return;
|
|
}
|
|
|
|
MemoryStream stream = new MemoryStream();
|
|
XmlWriter xw = XmlWriter.Create(stream);
|
|
xw.WriteStartElement("temp");
|
|
|
|
if (addressing == AddressingVersion.WSAddressing10)
|
|
{
|
|
xw.WriteAttributeString("xmlns", MetadataStrings.Addressing10.Prefix, null, MetadataStrings.Addressing10.NamespaceUri);
|
|
}
|
|
else if (addressing == AddressingVersion.WSAddressingAugust2004)
|
|
{
|
|
xw.WriteAttributeString("xmlns", MetadataStrings.Addressing200408.Prefix, null, MetadataStrings.Addressing200408.NamespaceUri);
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR.GetString(SR.AddressingVersionNotSupported, addressing)));
|
|
}
|
|
|
|
addr.WriteTo(addressing, xw);
|
|
xw.WriteEndElement();
|
|
|
|
xw.Flush();
|
|
stream.Seek(0, SeekOrigin.Begin);
|
|
|
|
XmlReader xr = XmlReader.Create(stream);
|
|
xr.MoveToContent();
|
|
XmlElement endpointRef = (XmlElement)XmlDoc.ReadNode(xr).ChildNodes[0];
|
|
|
|
wsdlPort.Extensions.Add(endpointRef);
|
|
}
|
|
|
|
internal static void AddWSAddressingAssertion(MetadataExporter exporter, PolicyConversionContext context, AddressingVersion addressVersion)
|
|
{
|
|
XmlElement addressingAssertion;
|
|
if (addressVersion == AddressingVersion.WSAddressingAugust2004)
|
|
{
|
|
addressingAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing200408.Policy.Prefix,
|
|
MetadataStrings.Addressing200408.Policy.UsingAddressing,
|
|
MetadataStrings.Addressing200408.Policy.NamespaceUri);
|
|
}
|
|
else if (addressVersion == AddressingVersion.WSAddressing10)
|
|
{
|
|
if (exporter.PolicyVersion == PolicyVersion.Policy12)
|
|
{
|
|
addressingAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing10.WsdlBindingPolicy.Prefix,
|
|
MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing,
|
|
MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri);
|
|
}
|
|
else
|
|
{
|
|
addressingAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing10.MetadataPolicy.Prefix,
|
|
MetadataStrings.Addressing10.MetadataPolicy.Addressing,
|
|
MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri);
|
|
|
|
// All of our existing transports are anonymous, so default to it.
|
|
SupportedAddressingMode mode = SupportedAddressingMode.Anonymous;
|
|
string key = typeof(SupportedAddressingMode).Name;
|
|
|
|
if (exporter.State.ContainsKey(key) && exporter.State[key] is SupportedAddressingMode)
|
|
{
|
|
mode = (SupportedAddressingMode)exporter.State[key];
|
|
if (!SupportedAddressingModeHelper.IsDefined(mode))
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SupportedAddressingModeNotSupported, mode)));
|
|
}
|
|
|
|
if (mode != SupportedAddressingMode.Mixed)
|
|
{
|
|
string responsesAssertionLocalName;
|
|
if (mode == SupportedAddressingMode.Anonymous)
|
|
{
|
|
responsesAssertionLocalName = MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses;
|
|
}
|
|
else
|
|
{
|
|
responsesAssertionLocalName = MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses;
|
|
}
|
|
|
|
XmlElement innerPolicyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.Policy,
|
|
MetadataStrings.WSPolicy.NamespaceUri15);
|
|
|
|
XmlElement responsesAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing10.MetadataPolicy.Prefix,
|
|
responsesAssertionLocalName,
|
|
MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri);
|
|
|
|
innerPolicyElement.AppendChild(responsesAssertion);
|
|
addressingAssertion.AppendChild(innerPolicyElement);
|
|
}
|
|
}
|
|
}
|
|
else if (addressVersion == AddressingVersion.None)
|
|
{
|
|
// do nothing
|
|
addressingAssertion = null;
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR.GetString(SR.AddressingVersionNotSupported, addressVersion)));
|
|
}
|
|
|
|
if (addressingAssertion != null)
|
|
{
|
|
context.GetBindingAssertions().Add(addressingAssertion);
|
|
}
|
|
}
|
|
}
|
|
|
|
class WSPolicyAttachmentHelper
|
|
{
|
|
PolicyVersion policyVersion;
|
|
internal WSPolicyAttachmentHelper(PolicyVersion policyVersion)
|
|
{
|
|
this.policyVersion = policyVersion;
|
|
}
|
|
|
|
internal void AttachPolicy(ServiceEndpoint endpoint, WsdlEndpointConversionContext endpointContext, PolicyConversionContext policyContext)
|
|
{
|
|
SortedList<string, string> policyKeys = new SortedList<string, string>();
|
|
NamingHelper.DoesNameExist policyKeyIsUnique
|
|
= delegate(string name, object nameCollection)
|
|
{
|
|
return policyKeys.ContainsKey(name);
|
|
};
|
|
|
|
string key, keyBase;
|
|
ICollection<XmlElement> assertions;
|
|
|
|
WsdlNS.ServiceDescription policyWsdl = endpointContext.WsdlBinding.ServiceDescription;
|
|
|
|
assertions = policyContext.GetBindingAssertions();
|
|
|
|
// Add [wsdl:Binding] level Policy
|
|
WsdlNS.Binding wsdlBinding = endpointContext.WsdlBinding;
|
|
if (assertions.Count > 0)
|
|
{
|
|
keyBase = CreateBindingPolicyKey(wsdlBinding);
|
|
key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
|
|
policyKeys.Add(key, key);
|
|
AttachItemPolicy(assertions, key, policyWsdl, wsdlBinding);
|
|
}
|
|
|
|
foreach (OperationDescription operation in endpoint.Contract.Operations)
|
|
{
|
|
if (!WsdlExporter.OperationIsExportable(operation))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
assertions = policyContext.GetOperationBindingAssertions(operation);
|
|
|
|
// Add [wsdl:Binding/wsdl:operation] policy
|
|
if (assertions.Count > 0)
|
|
{
|
|
WsdlNS.OperationBinding wsdlOperationBinding = endpointContext.GetOperationBinding(operation);
|
|
keyBase = CreateOperationBindingPolicyKey(wsdlOperationBinding);
|
|
key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
|
|
policyKeys.Add(key, key);
|
|
AttachItemPolicy(assertions, key, policyWsdl, wsdlOperationBinding);
|
|
}
|
|
|
|
//
|
|
// Add [wsdl:Binding/wsdl:operation] child policy
|
|
//
|
|
|
|
foreach (MessageDescription message in operation.Messages)
|
|
{
|
|
assertions = policyContext.GetMessageBindingAssertions(message);
|
|
|
|
// Add [wsdl:Binding/wsdl:operation/wsdl:(input, output, message)] policy
|
|
if (assertions.Count > 0)
|
|
{
|
|
WsdlNS.MessageBinding wsdlMessageBinding = endpointContext.GetMessageBinding(message);
|
|
keyBase = CreateMessageBindingPolicyKey(wsdlMessageBinding, message.Direction);
|
|
key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
|
|
policyKeys.Add(key, key);
|
|
AttachItemPolicy(assertions, key, policyWsdl, wsdlMessageBinding);
|
|
}
|
|
}
|
|
|
|
foreach (FaultDescription fault in operation.Faults)
|
|
{
|
|
assertions = policyContext.GetFaultBindingAssertions(fault);
|
|
|
|
// Add [wsdl:Binding/wsdl:operation/wsdl:fault] policy
|
|
if (assertions.Count > 0)
|
|
{
|
|
WsdlNS.FaultBinding wsdlFaultBinding = endpointContext.GetFaultBinding(fault);
|
|
keyBase = CreateFaultBindingPolicyKey(wsdlFaultBinding);
|
|
key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
|
|
policyKeys.Add(key, key);
|
|
AttachItemPolicy(assertions, key, policyWsdl, wsdlFaultBinding);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AttachItemPolicy(ICollection<XmlElement> assertions, string key, WsdlNS.ServiceDescription policyWsdl, WsdlNS.DocumentableItem item)
|
|
{
|
|
string policyKey = InsertPolicy(key, policyWsdl, assertions);
|
|
InsertPolicyReference(policyKey, item);
|
|
}
|
|
|
|
void InsertPolicyReference(string policyKey, WsdlNS.DocumentableItem item)
|
|
{
|
|
//Create wsp:PolicyReference Element On DocumentableItem
|
|
//---------------------------------------------------------------------------------------------------------
|
|
XmlElement policyReferenceElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.PolicyReference,
|
|
policyVersion.Namespace);
|
|
|
|
//Create wsp:PolicyURIs Attribute On DocumentableItem
|
|
//---------------------------------------------------------------------------------------------------------
|
|
XmlAttribute uriAttribute = XmlDoc.CreateAttribute(MetadataStrings.WSPolicy.Attributes.URI);
|
|
|
|
uriAttribute.Value = policyKey;
|
|
policyReferenceElement.Attributes.Append(uriAttribute);
|
|
item.Extensions.Add(policyReferenceElement);
|
|
}
|
|
|
|
string InsertPolicy(string key, WsdlNS.ServiceDescription policyWsdl, ICollection<XmlElement> assertions)
|
|
{
|
|
// Create [wsp:Policy]
|
|
XmlElement policyElement = CreatePolicyElement(assertions);
|
|
|
|
//Create [wsp:Policy/@wsu:Id]
|
|
XmlAttribute idAttribute = XmlDoc.CreateAttribute(MetadataStrings.Wsu.Prefix,
|
|
MetadataStrings.Wsu.Attributes.Id,
|
|
MetadataStrings.Wsu.NamespaceUri);
|
|
idAttribute.Value = key;
|
|
policyElement.SetAttributeNode(idAttribute);
|
|
|
|
// Add wsp:Policy To WSDL
|
|
if (policyWsdl != null)
|
|
{
|
|
policyWsdl.Extensions.Add(policyElement);
|
|
}
|
|
|
|
return string.Format(CultureInfo.InvariantCulture, "#{0}", key);
|
|
}
|
|
|
|
XmlElement CreatePolicyElement(ICollection<XmlElement> assertions)
|
|
{
|
|
// Create [wsp:Policy]
|
|
XmlElement policyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.Policy,
|
|
policyVersion.Namespace);
|
|
|
|
// Create [wsp:Policy/wsp:ExactlyOne]
|
|
XmlElement exactlyOneElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.ExactlyOne,
|
|
policyVersion.Namespace);
|
|
policyElement.AppendChild(exactlyOneElement);
|
|
|
|
// Create [wsp:Policy/wsp:ExactlyOne/wsp:All]
|
|
XmlElement allElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.All,
|
|
policyVersion.Namespace);
|
|
exactlyOneElement.AppendChild(allElement);
|
|
|
|
// Add [wsp:Policy/wsp:ExactlyOne/wsp:All/*]
|
|
foreach (XmlElement assertion in assertions)
|
|
{
|
|
XmlNode iNode = XmlDoc.ImportNode(assertion, true);
|
|
allElement.AppendChild(iNode);
|
|
}
|
|
|
|
return policyElement;
|
|
}
|
|
|
|
static string CreateBindingPolicyKey(WsdlNS.Binding wsdlBinding)
|
|
{
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}_policy", wsdlBinding.Name);
|
|
}
|
|
|
|
static string CreateOperationBindingPolicyKey(WsdlNS.OperationBinding wsdlOperationBinding)
|
|
{
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_policy",
|
|
wsdlOperationBinding.Binding.Name,
|
|
wsdlOperationBinding.Name);
|
|
}
|
|
|
|
static string CreateMessageBindingPolicyKey(WsdlNS.MessageBinding wsdlMessageBinding, MessageDirection direction)
|
|
{
|
|
WsdlNS.OperationBinding wsdlOperationBinding = wsdlMessageBinding.OperationBinding;
|
|
WsdlNS.Binding wsdlBinding = wsdlOperationBinding.Binding;
|
|
|
|
if (direction == MessageDirection.Input)
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_Input_policy", wsdlBinding.Name, wsdlOperationBinding.Name);
|
|
else
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_output_policy", wsdlBinding.Name, wsdlOperationBinding.Name);
|
|
}
|
|
|
|
static string CreateFaultBindingPolicyKey(WsdlNS.FaultBinding wsdlFaultBinding)
|
|
{
|
|
WsdlNS.OperationBinding wsdlOperationBinding = wsdlFaultBinding.OperationBinding;
|
|
WsdlNS.Binding wsdlBinding = wsdlOperationBinding.Binding;
|
|
if (string.IsNullOrEmpty(wsdlFaultBinding.Name))
|
|
{
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_Fault", wsdlBinding.Name, wsdlOperationBinding.Name);
|
|
}
|
|
else
|
|
{
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_{2}_Fault", wsdlBinding.Name, wsdlOperationBinding.Name, wsdlFaultBinding.Name);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class WsdlNamespaceHelper
|
|
{
|
|
XmlSerializerNamespaces xmlSerializerNamespaces;
|
|
PolicyVersion policyVersion;
|
|
internal XmlSerializerNamespaces SerializerNamespaces
|
|
{
|
|
get
|
|
{
|
|
if (xmlSerializerNamespaces == null)
|
|
{
|
|
XmlSerializerNamespaceWrapper namespaces = new XmlSerializerNamespaceWrapper();
|
|
namespaces.Add("wsdl", WsdlNS.ServiceDescription.Namespace);
|
|
namespaces.Add("xsd", XmlSchema.Namespace);
|
|
namespaces.Add(MetadataStrings.WSPolicy.Prefix, policyVersion.Namespace);
|
|
namespaces.Add(MetadataStrings.Wsu.Prefix, MetadataStrings.Wsu.NamespaceUri);
|
|
namespaces.Add(MetadataStrings.Addressing200408.Prefix, MetadataStrings.Addressing200408.NamespaceUri);
|
|
namespaces.Add(MetadataStrings.Addressing200408.Policy.Prefix, MetadataStrings.Addressing200408.Policy.NamespaceUri);
|
|
namespaces.Add(MetadataStrings.Addressing10.Prefix, MetadataStrings.Addressing10.NamespaceUri);
|
|
namespaces.Add(MetadataStrings.Addressing10.WsdlBindingPolicy.Prefix, MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri);
|
|
namespaces.Add(MetadataStrings.Addressing10.MetadataPolicy.Prefix, MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri);
|
|
namespaces.Add(MetadataStrings.MetadataExchangeStrings.Prefix, MetadataStrings.MetadataExchangeStrings.Namespace);
|
|
namespaces.Add(NetSessionHelper.Prefix, NetSessionHelper.NamespaceUri);
|
|
|
|
namespaces.Add("soapenc", "http://schemas.xmlsoap.org/soap/encoding/");
|
|
namespaces.Add("soap12", "http://schemas.xmlsoap.org/wsdl/soap12/");
|
|
namespaces.Add("soap", "http://schemas.xmlsoap.org/wsdl/soap/");
|
|
|
|
xmlSerializerNamespaces = namespaces.GetNamespaces();
|
|
}
|
|
return xmlSerializerNamespaces;
|
|
}
|
|
}
|
|
|
|
internal WsdlNamespaceHelper(PolicyVersion policyVersion)
|
|
{
|
|
this.policyVersion = policyVersion;
|
|
}
|
|
|
|
// doesn't care if you add a duplicate prefix
|
|
class XmlSerializerNamespaceWrapper
|
|
{
|
|
readonly XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
|
|
readonly Dictionary<string, string> lookup = new Dictionary<string, string>();
|
|
|
|
internal void Add(string prefix, string namespaceUri)
|
|
{
|
|
if (!lookup.ContainsKey(prefix))
|
|
{
|
|
namespaces.Add(prefix, namespaceUri);
|
|
lookup.Add(prefix, namespaceUri);
|
|
}
|
|
}
|
|
|
|
internal XmlSerializerNamespaces GetNamespaces()
|
|
{
|
|
return namespaces;
|
|
}
|
|
}
|
|
|
|
internal static string FindOrCreatePrefix(string prefixBase, string ns, params WsdlNS.DocumentableItem[] scopes)
|
|
{
|
|
if (!(scopes.Length > 0))
|
|
{
|
|
Fx.Assert("You must pass at least one namespaceScope");
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "You must pass at least one namespaceScope")));
|
|
}
|
|
string prefix = null;
|
|
|
|
if (string.IsNullOrEmpty(ns))
|
|
{
|
|
prefix = string.Empty;
|
|
}
|
|
else
|
|
{
|
|
//See if a prefix for the namespace has already been defined at one of the scopes
|
|
for (int j = 0; j < scopes.Length; j++)
|
|
if (TryMatchNamespace(scopes[j].Namespaces.ToArray(), ns, out prefix))
|
|
return prefix;
|
|
|
|
// Create prefix definition at the nearest scope.
|
|
int i = 0;
|
|
prefix = prefixBase + i.ToString(CultureInfo.InvariantCulture);
|
|
|
|
//[....], consider do we need to check at higher scopes as well?
|
|
while (PrefixExists(scopes[0].Namespaces.ToArray(), prefix))
|
|
prefix = prefixBase + (++i).ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
scopes[0].Namespaces.Add(prefix, ns);
|
|
|
|
return prefix;
|
|
}
|
|
|
|
static bool PrefixExists(XmlQualifiedName[] prefixDefinitions, string prefix)
|
|
{
|
|
return Array.Exists<XmlQualifiedName>(prefixDefinitions,
|
|
delegate(XmlQualifiedName prefixDef)
|
|
{
|
|
if (prefixDef.Name == prefix)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
}
|
|
|
|
static bool TryMatchNamespace(XmlQualifiedName[] prefixDefinitions, string ns, out string prefix)
|
|
{
|
|
string foundPrefix = null;
|
|
Array.Find<XmlQualifiedName>(prefixDefinitions,
|
|
delegate(XmlQualifiedName prefixDef)
|
|
{
|
|
if (prefixDef.Namespace == ns)
|
|
{
|
|
foundPrefix = prefixDef.Name;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
prefix = foundPrefix;
|
|
return foundPrefix != null;
|
|
}
|
|
}
|
|
|
|
internal static class WsdlNamingHelper
|
|
{
|
|
internal static XmlQualifiedName GetPortTypeQName(ContractDescription contract)
|
|
{
|
|
return new XmlQualifiedName(contract.Name, contract.Namespace);
|
|
}
|
|
|
|
internal static XmlQualifiedName GetBindingQName(ServiceEndpoint endpoint, WsdlExporter exporter, out bool wasUniquified)
|
|
{
|
|
// due to problems in Sysytem.Web.Services.Descriprion.ServiceDescription.Write() (double encoding) method we cannot use encoded names for
|
|
// wsdl:binding item: we need to make sure that XmlConvert.EncodeLocalName will not find any problems with the name, and leave it unchanged.
|
|
// consider changing the name here to something that will not be encoded by XmlSerializer (GenerateSimpleXmlName()?)
|
|
string localName = endpoint.Name;
|
|
|
|
string bindingWsdlNamespace = endpoint.Binding.Namespace;
|
|
string uniquifiedLocalName = NamingHelper.GetUniqueName(localName, WsdlBindingQNameExists(exporter, bindingWsdlNamespace), null);
|
|
wasUniquified = localName != uniquifiedLocalName;
|
|
|
|
return new XmlQualifiedName(uniquifiedLocalName, bindingWsdlNamespace);
|
|
}
|
|
|
|
static NamingHelper.DoesNameExist WsdlBindingQNameExists(WsdlExporter exporter, string bindingWsdlNamespace)
|
|
{
|
|
return delegate(string localName, object nameCollection)
|
|
{
|
|
XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(localName, bindingWsdlNamespace);
|
|
WsdlNS.ServiceDescription wsdl = exporter.wsdlDocuments[bindingWsdlNamespace];
|
|
if (wsdl != null && wsdl.Bindings[localName] != null)
|
|
return true;
|
|
|
|
return false;
|
|
};
|
|
}
|
|
|
|
|
|
|
|
internal static string GetPortName(ServiceEndpoint endpoint, WsdlNS.Service wsdlService)
|
|
{
|
|
return NamingHelper.GetUniqueName(endpoint.Name, ServiceContainsPort(wsdlService), null);
|
|
}
|
|
|
|
static NamingHelper.DoesNameExist ServiceContainsPort(WsdlNS.Service service)
|
|
{
|
|
return delegate(string portName, object nameCollection)
|
|
{
|
|
foreach (WsdlNS.Port port in service.Ports)
|
|
if (port.Name == portName)
|
|
return true;
|
|
return false;
|
|
};
|
|
}
|
|
|
|
internal static string GetWsdlOperationName(OperationDescription operationDescription, ContractDescription parentContractDescription)
|
|
{
|
|
return operationDescription.Name;
|
|
}
|
|
}
|
|
|
|
internal static class NetSessionHelper
|
|
{
|
|
internal const string NamespaceUri = "http://schemas.microsoft.com/ws/2005/12/wsdl/contract";
|
|
internal const string Prefix = "msc";
|
|
internal const string UsingSession = "usingSession";
|
|
internal const string IsInitiating = "isInitiating";
|
|
internal const string IsTerminating = "isTerminating";
|
|
internal const string True = "true";
|
|
internal const string False = "false";
|
|
|
|
internal static void AddUsingSessionAttributeIfNeeded(WsdlNS.PortType wsdlPortType, ContractDescription contract)
|
|
{
|
|
bool sessionValue;
|
|
|
|
if (contract.SessionMode == SessionMode.Required)
|
|
{
|
|
sessionValue = true;
|
|
}
|
|
else if (contract.SessionMode == SessionMode.NotAllowed)
|
|
{
|
|
sessionValue = false;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
wsdlPortType.ExtensibleAttributes = CloneAndAddToAttributes(wsdlPortType.ExtensibleAttributes, NetSessionHelper.Prefix,
|
|
NetSessionHelper.UsingSession, NetSessionHelper.NamespaceUri, ToValue(sessionValue));
|
|
}
|
|
|
|
internal static void AddInitiatingTerminatingAttributesIfNeeded(WsdlNS.Operation wsdlOperation,
|
|
OperationDescription operation, ContractDescription contract)
|
|
{
|
|
if (contract.SessionMode == SessionMode.Required)
|
|
{
|
|
AddInitiatingAttribute(wsdlOperation, operation.IsInitiating);
|
|
AddTerminatingAttribute(wsdlOperation, operation.IsTerminating);
|
|
}
|
|
}
|
|
|
|
static void AddInitiatingAttribute(System.Web.Services.Description.Operation wsdlOperation, bool isInitiating)
|
|
{
|
|
wsdlOperation.ExtensibleAttributes = CloneAndAddToAttributes(wsdlOperation.ExtensibleAttributes, NetSessionHelper.Prefix,
|
|
NetSessionHelper.IsInitiating, NetSessionHelper.NamespaceUri, ToValue(isInitiating));
|
|
}
|
|
|
|
static void AddTerminatingAttribute(System.Web.Services.Description.Operation wsdlOperation, bool isTerminating)
|
|
{
|
|
wsdlOperation.ExtensibleAttributes = CloneAndAddToAttributes(wsdlOperation.ExtensibleAttributes, NetSessionHelper.Prefix,
|
|
NetSessionHelper.IsTerminating, NetSessionHelper.NamespaceUri, ToValue(isTerminating));
|
|
}
|
|
|
|
static XmlAttribute[] CloneAndAddToAttributes(XmlAttribute[] originalAttributes, string prefix, string localName, string ns, string value)
|
|
{
|
|
XmlAttribute newAttribute = XmlDoc.CreateAttribute(prefix, localName, ns);
|
|
newAttribute.Value = value;
|
|
|
|
int originalAttributeCount = 0;
|
|
if (originalAttributes != null)
|
|
originalAttributeCount = originalAttributes.Length;
|
|
|
|
XmlAttribute[] attributes = new XmlAttribute[originalAttributeCount + 1];
|
|
|
|
if (originalAttributes != null)
|
|
originalAttributes.CopyTo(attributes, 0);
|
|
|
|
attributes[attributes.Length - 1] = newAttribute;
|
|
|
|
return attributes;
|
|
}
|
|
|
|
static string ToValue(bool b)
|
|
{
|
|
return b ? NetSessionHelper.True : NetSessionHelper.False;
|
|
}
|
|
}
|
|
|
|
void CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)
|
|
{
|
|
try
|
|
{
|
|
extension.ExportContract(this, contractContext);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThrowExtensionException(contractContext.Contract, extension, e));
|
|
}
|
|
}
|
|
|
|
void CallExtension(WsdlEndpointConversionContext endpointContext, IWsdlExportExtension extension)
|
|
{
|
|
try
|
|
{
|
|
extension.ExportEndpoint(this, endpointContext);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThrowExtensionException(endpointContext.Endpoint, extension, e));
|
|
}
|
|
}
|
|
|
|
Exception ThrowExtensionException(ContractDescription contract, IWsdlExportExtension exporter, Exception e)
|
|
{
|
|
string contractIdentifier = new XmlQualifiedName(contract.Name, contract.Namespace).ToString();
|
|
string errorMessage = SR.GetString(SR.WsdlExtensionContractExportError, exporter.GetType(), contractIdentifier);
|
|
|
|
return new InvalidOperationException(errorMessage, e);
|
|
}
|
|
|
|
Exception ThrowExtensionException(ServiceEndpoint endpoint, IWsdlExportExtension exporter, Exception e)
|
|
{
|
|
string endpointIdentifier;
|
|
if (endpoint.Address != null && endpoint.Address.Uri != null)
|
|
endpointIdentifier = endpoint.Address.Uri.ToString();
|
|
else
|
|
endpointIdentifier = String.Format(CultureInfo.InvariantCulture,
|
|
"Contract={1}:{0} ,Binding={3}:{2}",
|
|
endpoint.Contract.Name,
|
|
endpoint.Contract.Namespace,
|
|
endpoint.Binding.Name,
|
|
endpoint.Binding.Namespace);
|
|
|
|
string errorMessage = SR.GetString(SR.WsdlExtensionEndpointExportError, exporter.GetType(), endpointIdentifier);
|
|
|
|
return new InvalidOperationException(errorMessage, e);
|
|
}
|
|
|
|
sealed class BindingDictionaryKey
|
|
{
|
|
public readonly ContractDescription Contract;
|
|
public readonly Binding Binding;
|
|
|
|
public BindingDictionaryKey(ContractDescription contract, Binding binding)
|
|
{
|
|
this.Contract = contract;
|
|
this.Binding = binding;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
BindingDictionaryKey key = obj as BindingDictionaryKey;
|
|
if (key != null && key.Binding == this.Binding && key.Contract == this.Contract)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return this.Contract.GetHashCode() ^ this.Binding.GetHashCode();
|
|
}
|
|
}
|
|
|
|
sealed class EndpointDictionaryKey
|
|
{
|
|
public readonly ServiceEndpoint Endpoint;
|
|
public readonly XmlQualifiedName ServiceQName;
|
|
|
|
public EndpointDictionaryKey(ServiceEndpoint endpoint, XmlQualifiedName serviceQName)
|
|
{
|
|
this.Endpoint = endpoint;
|
|
this.ServiceQName = serviceQName;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
EndpointDictionaryKey key = obj as EndpointDictionaryKey;
|
|
if (key != null && key.Endpoint == this.Endpoint && key.ServiceQName == this.ServiceQName)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return this.Endpoint.GetHashCode() ^ this.ServiceQName.GetHashCode();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|