1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 
5 namespace System.ServiceModel.Description
6 {
7     using System.Collections;
8     using System.Collections.Generic;
9     using System.Globalization;
10     using System.IO;
11     using System.Runtime;
12     using System.ServiceModel;
13     using System.ServiceModel.Channels;
14     using System.Xml;
15     using System.Xml.Schema;
16     using System.Xml.Serialization;
17     using WsdlNS = System.Web.Services.Description;
18 
19     public class WsdlExporter : MetadataExporter
20     {
21         static XmlDocument xmlDocument;
22         bool isFaulted = false;
23 
24 
25         WsdlNS.ServiceDescriptionCollection wsdlDocuments = new WsdlNS.ServiceDescriptionCollection();
26         XmlSchemaSet xmlSchemas = WsdlExporter.GetEmptySchemaSet();
27 
28         Dictionary<ContractDescription, WsdlContractConversionContext> exportedContracts
29             = new Dictionary<ContractDescription, WsdlContractConversionContext>();
30         Dictionary<BindingDictionaryKey, WsdlEndpointConversionContext> exportedBindings = new Dictionary<BindingDictionaryKey, WsdlEndpointConversionContext>();
31         Dictionary<EndpointDictionaryKey, ServiceEndpoint> exportedEndpoints = new Dictionary<EndpointDictionaryKey, ServiceEndpoint>();
32 
ExportContract(ContractDescription contract)33         public override void ExportContract(ContractDescription contract)
34         {
35             if (this.isFaulted)
36                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlExporterIsFaulted)));
37 
38             if (contract == null)
39                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
40 
41             if (!this.exportedContracts.ContainsKey(contract))
42             {
43                 try
44                 {
45                     WsdlNS.PortType wsdlPortType = CreateWsdlPortType(contract);
46                     WsdlContractConversionContext contractContext;
47 
48 
49                     contractContext = new WsdlContractConversionContext(contract, wsdlPortType);
50 
51                     foreach (OperationDescription operation in contract.Operations)
52                     {
53                         bool isWildcardAction;
54                         if (!OperationIsExportable(operation, out isWildcardAction))
55                         {
56                             string warningMsg = isWildcardAction ? SR.GetString(SR.WarnSkippingOpertationWithWildcardAction, contract.Name, contract.Namespace, operation.Name)
57                                 : SR.GetString(SR.WarnSkippingOpertationWithSessionOpenNotificationEnabled, "Action", OperationDescription.SessionOpenedAction, contract.Name, contract.Namespace, operation.Name);
58 
59                             LogExportWarning(warningMsg);
60                             continue;
61                         }
62 
63                         WsdlNS.Operation wsdlOperation = CreateWsdlOperation(operation, contract);
64                         wsdlPortType.Operations.Add(wsdlOperation);
65 
66                         contractContext.AddOperation(operation, wsdlOperation);
67 
68                         foreach (MessageDescription message in operation.Messages)
69                         {
70                             //Create Operation Message
71                             WsdlNS.OperationMessage wsdlOperationMessage = CreateWsdlOperationMessage(message);
72                             wsdlOperation.Messages.Add(wsdlOperationMessage);
73                             contractContext.AddMessage(message, wsdlOperationMessage);
74                         }
75 
76                         foreach (FaultDescription fault in operation.Faults)
77                         {
78                             //Create Operation Fault
79                             WsdlNS.OperationFault wsdlOperationFault = CreateWsdlOperationFault(fault);
80                             wsdlOperation.Faults.Add(wsdlOperationFault);
81                             contractContext.AddFault(fault, wsdlOperationFault);
82                         }
83                     }
84 
85                     CallExportContract(contractContext);
86 
87                     exportedContracts.Add(contract, contractContext);
88                 }
89                 catch
90                 {
91                     isFaulted = true;
92                     throw;
93                 }
94             }
95         }
96 
ExportEndpoint(ServiceEndpoint endpoint)97         public override void ExportEndpoint(ServiceEndpoint endpoint)
98         {
99             if (this.isFaulted)
100                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlExporterIsFaulted)));
101 
102             if (endpoint == null)
103                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
104 
105             ExportEndpoint(endpoint, new XmlQualifiedName(NamingHelper.DefaultServiceName, NamingHelper.DefaultNamespace), null);
106         }
107 
ExportEndpoints(IEnumerable<ServiceEndpoint> endpoints, XmlQualifiedName wsdlServiceQName)108         public void ExportEndpoints(IEnumerable<ServiceEndpoint> endpoints, XmlQualifiedName wsdlServiceQName)
109         {
110             this.ExportEndpoints(endpoints, wsdlServiceQName, null);
111         }
112 
ExportEndpoints(IEnumerable<ServiceEndpoint> endpoints, XmlQualifiedName wsdlServiceQName, BindingParameterCollection bindingParameters)113         internal void ExportEndpoints(IEnumerable<ServiceEndpoint> endpoints, XmlQualifiedName wsdlServiceQName, BindingParameterCollection bindingParameters)
114         {
115             if (this.isFaulted)
116                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlExporterIsFaulted)));
117 
118             if (endpoints == null)
119                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoints");
120             if (wsdlServiceQName == null)
121                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlServiceQName");
122 
123             foreach (ServiceEndpoint endpoint in endpoints)
124             {
125                 ExportEndpoint(endpoint, wsdlServiceQName, bindingParameters);
126             }
127         }
128 
GetGeneratedMetadata()129         public override MetadataSet GetGeneratedMetadata()
130         {
131             MetadataSet set = new MetadataSet();
132 
133             foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
134                 set.MetadataSections.Add(MetadataSection.CreateFromServiceDescription(wsdl));
135 
136             foreach (XmlSchema schema in xmlSchemas.Schemas())
137                 set.MetadataSections.Add(MetadataSection.CreateFromSchema(schema));
138 
139             return set;
140         }
141 
142         public WsdlNS.ServiceDescriptionCollection GeneratedWsdlDocuments { get { return wsdlDocuments; } }
143         public XmlSchemaSet GeneratedXmlSchemas { get { return xmlSchemas; } }
144 
ExportEndpoint(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, BindingParameterCollection bindingParameters)145         void ExportEndpoint(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, BindingParameterCollection bindingParameters)
146         {
147             if (endpoint.Binding == null)
148                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.EndpointsMustHaveAValidBinding1, endpoint.Name)));
149 
150             EndpointDictionaryKey endpointKey = new EndpointDictionaryKey(endpoint, wsdlServiceQName);
151 
152             try
153             {
154                 if (exportedEndpoints.ContainsKey(endpointKey))
155                     return;
156 
157                 this.ExportContract(endpoint.Contract);
158 
159                 // Retreive Conversion Context for Contract;
160                 // Note: Contract must have already been exported at this point.
161                 WsdlContractConversionContext contractContext = this.exportedContracts[endpoint.Contract];
162 
163 
164                 bool newWsdlBinding, bindingNameWasUniquified;
165                 WsdlNS.Port wsdlPort;
166                 WsdlNS.Binding wsdlBinding;
167                 wsdlBinding = CreateWsdlBindingAndPort(endpoint, wsdlServiceQName, out wsdlPort, out newWsdlBinding, out bindingNameWasUniquified);
168 
169 
170                 if (!newWsdlBinding && wsdlPort == null)
171                     return;
172 
173                 // Create an Endpoint conversion context based on
174                 // the contract's conversion context (reuse contract correlation information)
175                 WsdlEndpointConversionContext endpointContext;
176                 if (newWsdlBinding)
177                 {
178                     endpointContext = new WsdlEndpointConversionContext(contractContext, endpoint, wsdlBinding, wsdlPort);
179 
180                     foreach (OperationDescription operation in endpoint.Contract.Operations)
181                     {
182                         if (!WsdlExporter.OperationIsExportable(operation))
183                         {
184                             continue;
185                         }
186 
187                         WsdlNS.OperationBinding wsdlOperationBinding = CreateWsdlOperationBinding(endpoint.Contract, operation);
188                         wsdlBinding.Operations.Add(wsdlOperationBinding);
189 
190                         endpointContext.AddOperationBinding(operation, wsdlOperationBinding);
191 
192                         foreach (MessageDescription message in operation.Messages)
193                         {
194                             WsdlNS.MessageBinding wsdlMessageBinding = CreateWsdlMessageBinding(message, endpoint.Binding, wsdlOperationBinding);
195                             endpointContext.AddMessageBinding(message, wsdlMessageBinding);
196                         }
197 
198                         foreach (FaultDescription fault in operation.Faults)
199                         {
200                             WsdlNS.FaultBinding wsdlFaultBinding = CreateWsdlFaultBinding(fault, endpoint.Binding, wsdlOperationBinding);
201                             endpointContext.AddFaultBinding(fault, wsdlFaultBinding);
202                         }
203                     }
204 
205                     // CSDMain 180381:  Added internal functionality for passing BindingParameters into the ExportPolicy process via PolicyConversionContext.
206                     // However, in order to not change existing behavior, we only call the internal ExportPolicy method which accepts BindingParameters if they are not null
207                     // (non-null binding parameters can only be passed in via internal code paths).  Otherwise, we call the existing ExportPolicy method, just like before.
208                     PolicyConversionContext policyContext;
209                     if (bindingParameters == null)
210                     {
211                         policyContext = this.ExportPolicy(endpoint);
212                     }
213                     else
214                     {
215                         policyContext = this.ExportPolicy(endpoint, bindingParameters);
216                     }
217                     // consider factoring this out of wsdl exporter
218                     new WSPolicyAttachmentHelper(this.PolicyVersion).AttachPolicy(endpoint, endpointContext, policyContext);
219                     exportedBindings.Add(new BindingDictionaryKey(endpoint.Contract, endpoint.Binding), endpointContext);
220                 }
221                 else
222                 {
223                     endpointContext = new WsdlEndpointConversionContext(exportedBindings[new BindingDictionaryKey(endpoint.Contract, endpoint.Binding)], endpoint, wsdlPort);
224                 }
225 
226                 CallExportEndpoint(endpointContext);
227                 exportedEndpoints.Add(endpointKey, endpoint);
228                 if (bindingNameWasUniquified)
229                     Errors.Add(new MetadataConversionError(SR.GetString(SR.WarnDuplicateBindingQNameNameOnExport, endpoint.Binding.Name, endpoint.Binding.Namespace, endpoint.Contract.Name), true /*isWarning*/));
230             }
231             catch
232             {
233                 isFaulted = true;
234                 throw;
235             }
236         }
237 
CallExportEndpoint(WsdlEndpointConversionContext endpointContext)238         void CallExportEndpoint(WsdlEndpointConversionContext endpointContext)
239         {
240             foreach (IWsdlExportExtension extension in endpointContext.ExportExtensions)
241             {
242                 CallExtension(endpointContext, extension);
243             }
244         }
245 
CallExportContract(WsdlContractConversionContext contractContext)246         void CallExportContract(WsdlContractConversionContext contractContext)
247         {
248             foreach (IWsdlExportExtension extension in contractContext.ExportExtensions)
249             {
250                 CallExtension(contractContext, extension);
251             }
252         }
253 
CreateWsdlPortType(ContractDescription contract)254         WsdlNS.PortType CreateWsdlPortType(ContractDescription contract)
255         {
256             XmlQualifiedName wsdlPortTypeQName = WsdlNamingHelper.GetPortTypeQName(contract);
257 
258             WsdlNS.ServiceDescription wsdl = GetOrCreateWsdl(wsdlPortTypeQName.Namespace);
259             WsdlNS.PortType wsdlPortType = new WsdlNS.PortType();
260             wsdlPortType.Name = wsdlPortTypeQName.Name;
261             if (wsdl.PortTypes[wsdlPortType.Name] != null)
262                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.DuplicateContractQNameNameOnExport, contract.Name, contract.Namespace)));
263             NetSessionHelper.AddUsingSessionAttributeIfNeeded(wsdlPortType, contract);
264             wsdl.PortTypes.Add(wsdlPortType);
265 
266             return wsdlPortType;
267         }
268 
CreateWsdlOperation(OperationDescription operation, ContractDescription contract)269         WsdlNS.Operation CreateWsdlOperation(OperationDescription operation, ContractDescription contract)
270         {
271             WsdlNS.Operation wsdlOperation = new WsdlNS.Operation();
272             wsdlOperation.Name = WsdlNamingHelper.GetWsdlOperationName(operation, contract);
273             NetSessionHelper.AddInitiatingTerminatingAttributesIfNeeded(wsdlOperation, operation, contract);
274             return wsdlOperation;
275         }
276 
CreateWsdlOperationMessage(MessageDescription message)277         WsdlNS.OperationMessage CreateWsdlOperationMessage(MessageDescription message)
278         {
279             WsdlNS.OperationMessage wsdlOperationMessage;
280 
281             if (message.Direction == MessageDirection.Input)
282                 wsdlOperationMessage = new WsdlNS.OperationInput();
283             else
284                 wsdlOperationMessage = new WsdlNS.OperationOutput();
285 
286             if (!XmlName.IsNullOrEmpty(message.MessageName))
287                 wsdlOperationMessage.Name = message.MessageName.EncodedName;
288 
289             // consider factoring this out of wslExporter
290             WSAddressingHelper.AddActionAttribute(message.Action, wsdlOperationMessage, this.PolicyVersion);
291             return wsdlOperationMessage;
292         }
293 
CreateWsdlOperationFault(FaultDescription fault)294         WsdlNS.OperationFault CreateWsdlOperationFault(FaultDescription fault)
295         {
296             WsdlNS.OperationFault wsdlOperationFault;
297             wsdlOperationFault = new WsdlNS.OperationFault();
298 
299             // operation fault name must not be empty (FaultDescription checks this)
300             wsdlOperationFault.Name = fault.Name;
301 
302             // consider factoring this out of wslExporter
303             WSAddressingHelper.AddActionAttribute(fault.Action, wsdlOperationFault, this.PolicyVersion);
304             return wsdlOperationFault;
305         }
306 
CreateWsdlBindingAndPort(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, out WsdlNS.Port wsdlPort, out bool newBinding, out bool bindingNameWasUniquified)307         WsdlNS.Binding CreateWsdlBindingAndPort(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, out WsdlNS.Port wsdlPort, out bool newBinding, out bool bindingNameWasUniquified)
308         {
309             WsdlNS.ServiceDescription bindingWsdl;
310             WsdlNS.Binding wsdlBinding;
311             WsdlEndpointConversionContext bindingConversionContext;
312             XmlQualifiedName wsdlBindingQName;
313             XmlQualifiedName wsdlPortTypeQName;
314             bool printWsdlDeclaration = IsWsdlExportable(endpoint.Binding);
315 
316             if (!exportedBindings.TryGetValue(new BindingDictionaryKey(endpoint.Contract, endpoint.Binding), out bindingConversionContext))
317             {
318                 wsdlBindingQName = WsdlNamingHelper.GetBindingQName(endpoint, this, out bindingNameWasUniquified);
319                 bindingWsdl = GetOrCreateWsdl(wsdlBindingQName.Namespace);
320                 wsdlBinding = new WsdlNS.Binding();
321                 wsdlBinding.Name = wsdlBindingQName.Name;
322                 newBinding = true;
323 
324                 WsdlNS.PortType wsdlPortType = exportedContracts[endpoint.Contract].WsdlPortType;
325                 wsdlPortTypeQName = new XmlQualifiedName(wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace);
326                 wsdlBinding.Type = wsdlPortTypeQName;
327                 if (printWsdlDeclaration)
328                 {
329                     bindingWsdl.Bindings.Add(wsdlBinding);
330                 }
331                 WsdlExporter.EnsureWsdlContainsImport(bindingWsdl, wsdlPortTypeQName.Namespace);
332             }
333             else
334             {
335                 wsdlBindingQName = new XmlQualifiedName(bindingConversionContext.WsdlBinding.Name, bindingConversionContext.WsdlBinding.ServiceDescription.TargetNamespace);
336                 bindingNameWasUniquified = false;
337                 bindingWsdl = wsdlDocuments[wsdlBindingQName.Namespace];
338                 wsdlBinding = bindingWsdl.Bindings[wsdlBindingQName.Name];
339                 wsdlPortTypeQName = wsdlBinding.Type;
340                 newBinding = false;
341             }
342 
343 
344             //We can only create a Port if there is an address
345             if (endpoint.Address != null)
346             {
347                 WsdlNS.Service wsdlService = GetOrCreateWsdlService(wsdlServiceQName);
348 
349                 wsdlPort = new WsdlNS.Port();
350                 string wsdlPortName = WsdlNamingHelper.GetPortName(endpoint, wsdlService);
351                 wsdlPort.Name = wsdlPortName;
352                 wsdlPort.Binding = wsdlBindingQName;
353 
354                 WsdlNS.SoapAddressBinding addressBinding = SoapHelper.GetOrCreateSoapAddressBinding(wsdlBinding, wsdlPort, this);
355 
356                 if (addressBinding != null)
357                 {
358                     addressBinding.Location = endpoint.Address.Uri.AbsoluteUri;
359                 }
360 
361                 WsdlExporter.EnsureWsdlContainsImport(wsdlService.ServiceDescription, wsdlBindingQName.Namespace);
362                 if (printWsdlDeclaration)
363                 {
364                     wsdlService.Ports.Add(wsdlPort);
365                 }
366             }
367             else
368             {
369                 wsdlPort = null;
370             }
371 
372             return wsdlBinding;
373         }
374 
CreateWsdlOperationBinding(ContractDescription contract, OperationDescription operation)375         WsdlNS.OperationBinding CreateWsdlOperationBinding(ContractDescription contract, OperationDescription operation)
376         {
377             WsdlNS.OperationBinding wsdlOperationBinding = new WsdlNS.OperationBinding();
378             wsdlOperationBinding.Name = WsdlNamingHelper.GetWsdlOperationName(operation, contract);
379             return wsdlOperationBinding;
380         }
381 
CreateWsdlMessageBinding(MessageDescription messageDescription, Binding binding, WsdlNS.OperationBinding wsdlOperationBinding)382         WsdlNS.MessageBinding CreateWsdlMessageBinding(MessageDescription messageDescription, Binding binding, WsdlNS.OperationBinding wsdlOperationBinding)
383         {
384             WsdlNS.MessageBinding wsdlMessageBinding;
385             if (messageDescription.Direction == MessageDirection.Input)
386             {
387                 wsdlOperationBinding.Input = new WsdlNS.InputBinding();
388                 wsdlMessageBinding = wsdlOperationBinding.Input;
389             }
390             else
391             {
392                 wsdlOperationBinding.Output = new WsdlNS.OutputBinding();
393                 wsdlMessageBinding = wsdlOperationBinding.Output;
394             }
395 
396             if (!XmlName.IsNullOrEmpty(messageDescription.MessageName))
397                 wsdlMessageBinding.Name = messageDescription.MessageName.EncodedName;
398 
399             return wsdlMessageBinding;
400         }
401 
CreateWsdlFaultBinding(FaultDescription faultDescription, Binding binding, WsdlNS.OperationBinding wsdlOperationBinding)402         WsdlNS.FaultBinding CreateWsdlFaultBinding(FaultDescription faultDescription, Binding binding, WsdlNS.OperationBinding wsdlOperationBinding)
403         {
404             WsdlNS.FaultBinding wsdlFaultBinding = new WsdlNS.FaultBinding();
405             wsdlOperationBinding.Faults.Add(wsdlFaultBinding);
406             if (faultDescription.Name != null)
407                 wsdlFaultBinding.Name = faultDescription.Name;
408 
409             return wsdlFaultBinding;
410         }
411 
OperationIsExportable(OperationDescription operation)412         internal static bool OperationIsExportable(OperationDescription operation)
413         {
414             bool isWildcardAction;
415             return OperationIsExportable(operation, out isWildcardAction);
416         }
417 
OperationIsExportable(OperationDescription operation, out bool isWildcardAction)418         internal static bool OperationIsExportable(OperationDescription operation, out bool isWildcardAction)
419         {
420             isWildcardAction = false;
421 
422             if (operation.IsSessionOpenNotificationEnabled)
423             {
424                 return false;
425             }
426 
427             for (int i = 0; i < operation.Messages.Count; i++)
428             {
429                 if (operation.Messages[i].Action == MessageHeaders.WildcardAction)
430                 {
431                     isWildcardAction = true;
432                     return false;
433                 }
434             }
435             return true;
436         }
437 
IsBuiltInOperationBehavior(IWsdlExportExtension extension)438         internal static bool IsBuiltInOperationBehavior(IWsdlExportExtension extension)
439         {
440             DataContractSerializerOperationBehavior dcsob = extension as DataContractSerializerOperationBehavior;
441             if (dcsob != null)
442             {
443                 return dcsob.IsBuiltInOperationBehavior;
444             }
445 
446             XmlSerializerOperationBehavior xsob = extension as XmlSerializerOperationBehavior;
447             if (xsob != null)
448             {
449                 return xsob.IsBuiltInOperationBehavior;
450             }
451 
452             return false;
453         }
454 
455         static XmlDocument XmlDoc
456         {
457             get
458             {
459                 if (xmlDocument == null)
460                 {
461                     NameTable nameTable = new NameTable();
462                     nameTable.Add(MetadataStrings.WSPolicy.Elements.Policy);
463                     nameTable.Add(MetadataStrings.WSPolicy.Elements.All);
464                     nameTable.Add(MetadataStrings.WSPolicy.Elements.ExactlyOne);
465                     nameTable.Add(MetadataStrings.WSPolicy.Attributes.PolicyURIs);
466                     nameTable.Add(MetadataStrings.Wsu.Attributes.Id);
467                     nameTable.Add(MetadataStrings.Addressing200408.Policy.UsingAddressing);
468                     nameTable.Add(MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing);
469                     nameTable.Add(MetadataStrings.Addressing10.MetadataPolicy.Addressing);
470                     nameTable.Add(MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses);
471                     nameTable.Add(MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses);
472                     xmlDocument = new XmlDocument(nameTable);
473                 }
474                 return xmlDocument;
475             }
476         }
477 
478         // Generate WSDL Document if it doesn't already exist otherwise, return the appropriate WSDL document
GetOrCreateWsdl(string ns)479         internal WsdlNS.ServiceDescription GetOrCreateWsdl(string ns)
480         {
481             // NOTE: this method is not thread safe
482             WsdlNS.ServiceDescriptionCollection wsdlCollection = this.wsdlDocuments;
483             WsdlNS.ServiceDescription wsdl = wsdlCollection[ns];
484 
485             // Look for wsdl in service descriptions that have been created. If we cannot find it then we create it
486             if (wsdl == null)
487             {
488                 wsdl = new WsdlNS.ServiceDescription();
489                 wsdl.TargetNamespace = ns;
490 
491                 XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(new WsdlNamespaceHelper(this.PolicyVersion).SerializerNamespaces);
492                 if (!string.IsNullOrEmpty(wsdl.TargetNamespace))
493                     namespaces.Add("tns", wsdl.TargetNamespace);
494                 wsdl.Namespaces = namespaces;
495 
496                 wsdlCollection.Add(wsdl);
497             }
498 
499             return wsdl;
500         }
501 
GetOrCreateWsdlService(XmlQualifiedName wsdlServiceQName)502         WsdlNS.Service GetOrCreateWsdlService(XmlQualifiedName wsdlServiceQName)
503         {
504             // NOTE: this method is not thread safe
505 
506             WsdlNS.ServiceDescription wsdl = GetOrCreateWsdl(wsdlServiceQName.Namespace);
507 
508             WsdlNS.Service wsdlService = wsdl.Services[wsdlServiceQName.Name];
509             if (wsdlService == null)
510             {
511                 //Service not found. Create service.
512                 wsdlService = new WsdlNS.Service();
513                 wsdlService.Name = wsdlServiceQName.Name;
514 
515                 if (string.IsNullOrEmpty(wsdl.Name))
516                     wsdl.Name = wsdlService.Name;
517 
518                 wsdl.Services.Add(wsdlService);
519             }
520             return wsdlService;
521         }
522 
EnsureWsdlContainsImport(WsdlNS.ServiceDescription srcWsdl, string target)523         static void EnsureWsdlContainsImport(WsdlNS.ServiceDescription srcWsdl, string target)
524         {
525             if (srcWsdl.TargetNamespace == target)
526                 return;
527             // FindImport
528             foreach (WsdlNS.Import import in srcWsdl.Imports)
529             {
530                 if (import.Namespace == target)
531                     return;
532             }
533             {
534                 WsdlNS.Import import = new WsdlNS.Import();
535                 import.Location = null;
536                 import.Namespace = target;
537                 srcWsdl.Imports.Add(import);
538                 WsdlNamespaceHelper.FindOrCreatePrefix("i", target, srcWsdl);
539                 return;
540             }
541         }
542 
LogExportWarning(string warningMessage)543         void LogExportWarning(string warningMessage)
544         {
545             this.Errors.Add(new MetadataConversionError(warningMessage, true));
546         }
547 
GetEmptySchemaSet()548         static internal XmlSchemaSet GetEmptySchemaSet()
549         {
550             XmlSchemaSet schemaSet = new XmlSchemaSet();
551             schemaSet.XmlResolver = null;
552             return schemaSet;
553         }
554 
IsWsdlExportable(Binding binding)555         static bool IsWsdlExportable(Binding binding)
556         {
557             BindingElementCollection bindingElements = binding.CreateBindingElements();
558             if (bindingElements == null)
559             {
560                 return true;
561             }
562             foreach (BindingElement bindingElement in bindingElements)
563             {
564                 MessageEncodingBindingElement messageEncodingBindingElement = bindingElement as MessageEncodingBindingElement;
565                 if (messageEncodingBindingElement != null && !messageEncodingBindingElement.IsWsdlExportable)
566                 {
567                     return false;
568                 }
569             }
570             return true;
571         }
572 
573         internal static class WSAddressingHelper
574         {
AddActionAttribute(string actionUri, WsdlNS.OperationMessage wsdlOperationMessage, PolicyVersion policyVersion)575             internal static void AddActionAttribute(string actionUri, WsdlNS.OperationMessage wsdlOperationMessage, PolicyVersion policyVersion)
576             {
577                 XmlAttribute attribute;
578                 if (policyVersion == PolicyVersion.Policy12)
579                 {
580                     attribute = WsdlExporter.XmlDoc.CreateAttribute(MetadataStrings.AddressingWsdl.Prefix,
581                         MetadataStrings.AddressingWsdl.Action,
582                         MetadataStrings.AddressingWsdl.NamespaceUri);
583                 }
584                 else
585                 {
586                     attribute = WsdlExporter.XmlDoc.CreateAttribute(MetadataStrings.AddressingMetadata.Prefix,
587                         MetadataStrings.AddressingMetadata.Action,
588                         MetadataStrings.AddressingMetadata.NamespaceUri);
589                 }
590 
591                 attribute.Value = actionUri;
592                 wsdlOperationMessage.ExtensibleAttributes = new XmlAttribute[] { attribute };
593             }
594 
AddAddressToWsdlPort(WsdlNS.Port wsdlPort, EndpointAddress addr, AddressingVersion addressing)595             internal static void AddAddressToWsdlPort(WsdlNS.Port wsdlPort, EndpointAddress addr, AddressingVersion addressing)
596             {
597                 if (addressing == AddressingVersion.None)
598                 {
599                     return;
600                 }
601 
602                 MemoryStream stream = new MemoryStream();
603                 XmlWriter xw = XmlWriter.Create(stream);
604                 xw.WriteStartElement("temp");
605 
606                 if (addressing == AddressingVersion.WSAddressing10)
607                 {
608                     xw.WriteAttributeString("xmlns", MetadataStrings.Addressing10.Prefix, null, MetadataStrings.Addressing10.NamespaceUri);
609                 }
610                 else if (addressing == AddressingVersion.WSAddressingAugust2004)
611                 {
612                     xw.WriteAttributeString("xmlns", MetadataStrings.Addressing200408.Prefix, null, MetadataStrings.Addressing200408.NamespaceUri);
613                 }
614                 else
615                 {
616                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
617                         new InvalidOperationException(SR.GetString(SR.AddressingVersionNotSupported, addressing)));
618                 }
619 
620                 addr.WriteTo(addressing, xw);
621                 xw.WriteEndElement();
622 
623                 xw.Flush();
624                 stream.Seek(0, SeekOrigin.Begin);
625 
626                 XmlReader xr = XmlReader.Create(stream);
627                 xr.MoveToContent();
628                 XmlElement endpointRef = (XmlElement)XmlDoc.ReadNode(xr).ChildNodes[0];
629 
630                 wsdlPort.Extensions.Add(endpointRef);
631             }
632 
AddWSAddressingAssertion(MetadataExporter exporter, PolicyConversionContext context, AddressingVersion addressVersion)633             internal static void AddWSAddressingAssertion(MetadataExporter exporter, PolicyConversionContext context, AddressingVersion addressVersion)
634             {
635                 XmlElement addressingAssertion;
636                 if (addressVersion == AddressingVersion.WSAddressingAugust2004)
637                 {
638                     addressingAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing200408.Policy.Prefix,
639                         MetadataStrings.Addressing200408.Policy.UsingAddressing,
640                         MetadataStrings.Addressing200408.Policy.NamespaceUri);
641                 }
642                 else if (addressVersion == AddressingVersion.WSAddressing10)
643                 {
644                     if (exporter.PolicyVersion == PolicyVersion.Policy12)
645                     {
646                         addressingAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing10.WsdlBindingPolicy.Prefix,
647                             MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing,
648                             MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri);
649                     }
650                     else
651                     {
652                         addressingAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing10.MetadataPolicy.Prefix,
653                             MetadataStrings.Addressing10.MetadataPolicy.Addressing,
654                             MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri);
655 
656                         // All of our existing transports are anonymous, so default to it.
657                         SupportedAddressingMode mode = SupportedAddressingMode.Anonymous;
658                         string key = typeof(SupportedAddressingMode).Name;
659 
660                         if (exporter.State.ContainsKey(key) && exporter.State[key] is SupportedAddressingMode)
661                         {
662                             mode = (SupportedAddressingMode)exporter.State[key];
663                             if (!SupportedAddressingModeHelper.IsDefined(mode))
664                                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SupportedAddressingModeNotSupported, mode)));
665                         }
666 
667                         if (mode != SupportedAddressingMode.Mixed)
668                         {
669                             string responsesAssertionLocalName;
670                             if (mode == SupportedAddressingMode.Anonymous)
671                             {
672                                 responsesAssertionLocalName = MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses;
673                             }
674                             else
675                             {
676                                 responsesAssertionLocalName = MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses;
677                             }
678 
679                             XmlElement innerPolicyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
680                                     MetadataStrings.WSPolicy.Elements.Policy,
681                                     MetadataStrings.WSPolicy.NamespaceUri15);
682 
683                             XmlElement responsesAssertion = XmlDoc.CreateElement(MetadataStrings.Addressing10.MetadataPolicy.Prefix,
684                                     responsesAssertionLocalName,
685                                     MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri);
686 
687                             innerPolicyElement.AppendChild(responsesAssertion);
688                             addressingAssertion.AppendChild(innerPolicyElement);
689                         }
690                     }
691                 }
692                 else if (addressVersion == AddressingVersion.None)
693                 {
694                     // do nothing
695                     addressingAssertion = null;
696                 }
697                 else
698                 {
699                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
700                         new InvalidOperationException(SR.GetString(SR.AddressingVersionNotSupported, addressVersion)));
701                 }
702 
703                 if (addressingAssertion != null)
704                 {
705                     context.GetBindingAssertions().Add(addressingAssertion);
706                 }
707             }
708         }
709 
710         class WSPolicyAttachmentHelper
711         {
712             PolicyVersion policyVersion;
WSPolicyAttachmentHelper(PolicyVersion policyVersion)713             internal WSPolicyAttachmentHelper(PolicyVersion policyVersion)
714             {
715                 this.policyVersion = policyVersion;
716             }
717 
AttachPolicy(ServiceEndpoint endpoint, WsdlEndpointConversionContext endpointContext, PolicyConversionContext policyContext)718             internal void AttachPolicy(ServiceEndpoint endpoint, WsdlEndpointConversionContext endpointContext, PolicyConversionContext policyContext)
719             {
720                 SortedList<string, string> policyKeys = new SortedList<string, string>();
721                 NamingHelper.DoesNameExist policyKeyIsUnique
722                     = delegate(string name, object nameCollection)
723                     {
724                         return policyKeys.ContainsKey(name);
725                     };
726 
727                 string key, keyBase;
728                 ICollection<XmlElement> assertions;
729 
730                 WsdlNS.ServiceDescription policyWsdl = endpointContext.WsdlBinding.ServiceDescription;
731 
732                 assertions = policyContext.GetBindingAssertions();
733 
734                 // Add [wsdl:Binding] level Policy
735                 WsdlNS.Binding wsdlBinding = endpointContext.WsdlBinding;
736                 if (assertions.Count > 0)
737                 {
738                     keyBase = CreateBindingPolicyKey(wsdlBinding);
739                     key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
740                     policyKeys.Add(key, key);
741                     AttachItemPolicy(assertions, key, policyWsdl, wsdlBinding);
742                 }
743 
744                 foreach (OperationDescription operation in endpoint.Contract.Operations)
745                 {
746                     if (!WsdlExporter.OperationIsExportable(operation))
747                     {
748                         continue;
749                     }
750 
751                     assertions = policyContext.GetOperationBindingAssertions(operation);
752 
753                     // Add [wsdl:Binding/wsdl:operation] policy
754                     if (assertions.Count > 0)
755                     {
756                         WsdlNS.OperationBinding wsdlOperationBinding = endpointContext.GetOperationBinding(operation);
757                         keyBase = CreateOperationBindingPolicyKey(wsdlOperationBinding);
758                         key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
759                         policyKeys.Add(key, key);
760                         AttachItemPolicy(assertions, key, policyWsdl, wsdlOperationBinding);
761                     }
762 
763                     //
764                     // Add [wsdl:Binding/wsdl:operation] child policy
765                     //
766 
767                     foreach (MessageDescription message in operation.Messages)
768                     {
769                         assertions = policyContext.GetMessageBindingAssertions(message);
770 
771                         // Add [wsdl:Binding/wsdl:operation/wsdl:(input, output, message)] policy
772                         if (assertions.Count > 0)
773                         {
774                             WsdlNS.MessageBinding wsdlMessageBinding = endpointContext.GetMessageBinding(message);
775                             keyBase = CreateMessageBindingPolicyKey(wsdlMessageBinding, message.Direction);
776                             key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
777                             policyKeys.Add(key, key);
778                             AttachItemPolicy(assertions, key, policyWsdl, wsdlMessageBinding);
779                         }
780                     }
781 
782                     foreach (FaultDescription fault in operation.Faults)
783                     {
784                         assertions = policyContext.GetFaultBindingAssertions(fault);
785 
786                         // Add [wsdl:Binding/wsdl:operation/wsdl:fault] policy
787                         if (assertions.Count > 0)
788                         {
789                             WsdlNS.FaultBinding wsdlFaultBinding = endpointContext.GetFaultBinding(fault);
790                             keyBase = CreateFaultBindingPolicyKey(wsdlFaultBinding);
791                             key = NamingHelper.GetUniqueName(keyBase, policyKeyIsUnique, null);
792                             policyKeys.Add(key, key);
793                             AttachItemPolicy(assertions, key, policyWsdl, wsdlFaultBinding);
794                         }
795                     }
796                 }
797             }
798 
AttachItemPolicy(ICollection<XmlElement> assertions, string key, WsdlNS.ServiceDescription policyWsdl, WsdlNS.DocumentableItem item)799             void AttachItemPolicy(ICollection<XmlElement> assertions, string key, WsdlNS.ServiceDescription policyWsdl, WsdlNS.DocumentableItem item)
800             {
801                 string policyKey = InsertPolicy(key, policyWsdl, assertions);
802                 InsertPolicyReference(policyKey, item);
803             }
804 
InsertPolicyReference(string policyKey, WsdlNS.DocumentableItem item)805             void InsertPolicyReference(string policyKey, WsdlNS.DocumentableItem item)
806             {
807                 //Create wsp:PolicyReference Element On DocumentableItem
808                 //---------------------------------------------------------------------------------------------------------
809                 XmlElement policyReferenceElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
810                                                             MetadataStrings.WSPolicy.Elements.PolicyReference,
811                                                             policyVersion.Namespace);
812 
813                 //Create wsp:PolicyURIs Attribute On DocumentableItem
814                 //---------------------------------------------------------------------------------------------------------
815                 XmlAttribute uriAttribute = XmlDoc.CreateAttribute(MetadataStrings.WSPolicy.Attributes.URI);
816 
817                 uriAttribute.Value = policyKey;
818                 policyReferenceElement.Attributes.Append(uriAttribute);
819                 item.Extensions.Add(policyReferenceElement);
820             }
821 
InsertPolicy(string key, WsdlNS.ServiceDescription policyWsdl, ICollection<XmlElement> assertions)822             string InsertPolicy(string key, WsdlNS.ServiceDescription policyWsdl, ICollection<XmlElement> assertions)
823             {
824                 // Create [wsp:Policy]
825                 XmlElement policyElement = CreatePolicyElement(assertions);
826 
827                 //Create [wsp:Policy/@wsu:Id]
828                 XmlAttribute idAttribute = XmlDoc.CreateAttribute(MetadataStrings.Wsu.Prefix,
829                                                             MetadataStrings.Wsu.Attributes.Id,
830                                                             MetadataStrings.Wsu.NamespaceUri);
831                 idAttribute.Value = key;
832                 policyElement.SetAttributeNode(idAttribute);
833 
834                 // Add wsp:Policy To WSDL
835                 if (policyWsdl != null)
836                 {
837                     policyWsdl.Extensions.Add(policyElement);
838                 }
839 
840                 return string.Format(CultureInfo.InvariantCulture, "#{0}", key);
841             }
842 
CreatePolicyElement(ICollection<XmlElement> assertions)843             XmlElement CreatePolicyElement(ICollection<XmlElement> assertions)
844             {
845                 // Create [wsp:Policy]
846                 XmlElement policyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
847                                                             MetadataStrings.WSPolicy.Elements.Policy,
848                                                             policyVersion.Namespace);
849 
850                 // Create [wsp:Policy/wsp:ExactlyOne]
851                 XmlElement exactlyOneElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
852                                                             MetadataStrings.WSPolicy.Elements.ExactlyOne,
853                                                             policyVersion.Namespace);
854                 policyElement.AppendChild(exactlyOneElement);
855 
856                 // Create [wsp:Policy/wsp:ExactlyOne/wsp:All]
857                 XmlElement allElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
858                                                             MetadataStrings.WSPolicy.Elements.All,
859                                                             policyVersion.Namespace);
860                 exactlyOneElement.AppendChild(allElement);
861 
862                 // Add [wsp:Policy/wsp:ExactlyOne/wsp:All/*]
863                 foreach (XmlElement assertion in assertions)
864                 {
865                     XmlNode iNode = XmlDoc.ImportNode(assertion, true);
866                     allElement.AppendChild(iNode);
867                 }
868 
869                 return policyElement;
870             }
871 
CreateBindingPolicyKey(WsdlNS.Binding wsdlBinding)872             static string CreateBindingPolicyKey(WsdlNS.Binding wsdlBinding)
873             {
874                 return string.Format(CultureInfo.InvariantCulture, "{0}_policy", wsdlBinding.Name);
875             }
876 
CreateOperationBindingPolicyKey(WsdlNS.OperationBinding wsdlOperationBinding)877             static string CreateOperationBindingPolicyKey(WsdlNS.OperationBinding wsdlOperationBinding)
878             {
879                 return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_policy",
880                     wsdlOperationBinding.Binding.Name,
881                     wsdlOperationBinding.Name);
882             }
883 
CreateMessageBindingPolicyKey(WsdlNS.MessageBinding wsdlMessageBinding, MessageDirection direction)884             static string CreateMessageBindingPolicyKey(WsdlNS.MessageBinding wsdlMessageBinding, MessageDirection direction)
885             {
886                 WsdlNS.OperationBinding wsdlOperationBinding = wsdlMessageBinding.OperationBinding;
887                 WsdlNS.Binding wsdlBinding = wsdlOperationBinding.Binding;
888 
889                 if (direction == MessageDirection.Input)
890                     return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_Input_policy", wsdlBinding.Name, wsdlOperationBinding.Name);
891                 else
892                     return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_output_policy", wsdlBinding.Name, wsdlOperationBinding.Name);
893             }
894 
CreateFaultBindingPolicyKey(WsdlNS.FaultBinding wsdlFaultBinding)895             static string CreateFaultBindingPolicyKey(WsdlNS.FaultBinding wsdlFaultBinding)
896             {
897                 WsdlNS.OperationBinding wsdlOperationBinding = wsdlFaultBinding.OperationBinding;
898                 WsdlNS.Binding wsdlBinding = wsdlOperationBinding.Binding;
899                 if (string.IsNullOrEmpty(wsdlFaultBinding.Name))
900                 {
901                     return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_Fault", wsdlBinding.Name, wsdlOperationBinding.Name);
902                 }
903                 else
904                 {
905                     return string.Format(CultureInfo.InvariantCulture, "{0}_{1}_{2}_Fault", wsdlBinding.Name, wsdlOperationBinding.Name, wsdlFaultBinding.Name);
906                 }
907             }
908 
909         }
910 
911         class WsdlNamespaceHelper
912         {
913             XmlSerializerNamespaces xmlSerializerNamespaces;
914             PolicyVersion policyVersion;
915             internal XmlSerializerNamespaces SerializerNamespaces
916             {
917                 get
918                 {
919                     if (xmlSerializerNamespaces == null)
920                     {
921                         XmlSerializerNamespaceWrapper namespaces = new XmlSerializerNamespaceWrapper();
922                         namespaces.Add("wsdl", WsdlNS.ServiceDescription.Namespace);
923                         namespaces.Add("xsd", XmlSchema.Namespace);
924                         namespaces.Add(MetadataStrings.WSPolicy.Prefix, policyVersion.Namespace);
925                         namespaces.Add(MetadataStrings.Wsu.Prefix, MetadataStrings.Wsu.NamespaceUri);
926                         namespaces.Add(MetadataStrings.Addressing200408.Prefix, MetadataStrings.Addressing200408.NamespaceUri);
927                         namespaces.Add(MetadataStrings.Addressing200408.Policy.Prefix, MetadataStrings.Addressing200408.Policy.NamespaceUri);
928                         namespaces.Add(MetadataStrings.Addressing10.Prefix, MetadataStrings.Addressing10.NamespaceUri);
929                         namespaces.Add(MetadataStrings.Addressing10.WsdlBindingPolicy.Prefix, MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri);
930                         namespaces.Add(MetadataStrings.Addressing10.MetadataPolicy.Prefix, MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri);
931                         namespaces.Add(MetadataStrings.MetadataExchangeStrings.Prefix, MetadataStrings.MetadataExchangeStrings.Namespace);
932                         namespaces.Add(NetSessionHelper.Prefix, NetSessionHelper.NamespaceUri);
933 
934                         namespaces.Add("soapenc", "http://schemas.xmlsoap.org/soap/encoding/");
935                         namespaces.Add("soap12", "http://schemas.xmlsoap.org/wsdl/soap12/");
936                         namespaces.Add("soap", "http://schemas.xmlsoap.org/wsdl/soap/");
937 
938                         xmlSerializerNamespaces = namespaces.GetNamespaces();
939                     }
940                     return xmlSerializerNamespaces;
941                 }
942             }
943 
WsdlNamespaceHelper(PolicyVersion policyVersion)944             internal WsdlNamespaceHelper(PolicyVersion policyVersion)
945             {
946                 this.policyVersion = policyVersion;
947             }
948 
949             // doesn't care if you add a duplicate prefix
950             class XmlSerializerNamespaceWrapper
951             {
952                 readonly XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
953                 readonly Dictionary<string, string> lookup = new Dictionary<string, string>();
954 
Add(string prefix, string namespaceUri)955                 internal void Add(string prefix, string namespaceUri)
956                 {
957                     if (!lookup.ContainsKey(prefix))
958                     {
959                         namespaces.Add(prefix, namespaceUri);
960                         lookup.Add(prefix, namespaceUri);
961                     }
962                 }
963 
GetNamespaces()964                 internal XmlSerializerNamespaces GetNamespaces()
965                 {
966                     return namespaces;
967                 }
968             }
969 
FindOrCreatePrefix(string prefixBase, string ns, params WsdlNS.DocumentableItem[] scopes)970             internal static string FindOrCreatePrefix(string prefixBase, string ns, params WsdlNS.DocumentableItem[] scopes)
971             {
972                 if (!(scopes.Length > 0))
973                 {
974                     Fx.Assert("You must pass at least one namespaceScope");
975                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "You must pass at least one namespaceScope")));
976                 }
977                 string prefix = null;
978 
979                 if (string.IsNullOrEmpty(ns))
980                 {
981                     prefix = string.Empty;
982                 }
983                 else
984                 {
985                     //See if a prefix for the namespace has already been defined at one of the scopes
986                     for (int j = 0; j < scopes.Length; j++)
987                         if (TryMatchNamespace(scopes[j].Namespaces.ToArray(), ns, out prefix))
988                             return prefix;
989 
990                     // Create prefix definition at the nearest scope.
991                     int i = 0;
992                     prefix = prefixBase + i.ToString(CultureInfo.InvariantCulture);
993 
994                     //Microsoft, consider do we need to check at higher scopes as well?
995                     while (PrefixExists(scopes[0].Namespaces.ToArray(), prefix))
996                         prefix = prefixBase + (++i).ToString(CultureInfo.InvariantCulture);
997                 }
998                 scopes[0].Namespaces.Add(prefix, ns);
999 
1000                 return prefix;
1001             }
1002 
PrefixExists(XmlQualifiedName[] prefixDefinitions, string prefix)1003             static bool PrefixExists(XmlQualifiedName[] prefixDefinitions, string prefix)
1004             {
1005                 return Array.Exists<XmlQualifiedName>(prefixDefinitions,
1006                     delegate(XmlQualifiedName prefixDef)
1007                     {
1008                         if (prefixDef.Name == prefix)
1009                         {
1010                             return true;
1011                         }
1012                         return false;
1013                     });
1014 
1015             }
1016 
TryMatchNamespace(XmlQualifiedName[] prefixDefinitions, string ns, out string prefix)1017             static bool TryMatchNamespace(XmlQualifiedName[] prefixDefinitions, string ns, out string prefix)
1018             {
1019                 string foundPrefix = null;
1020                 Array.Find<XmlQualifiedName>(prefixDefinitions,
1021                     delegate(XmlQualifiedName prefixDef)
1022                     {
1023                         if (prefixDef.Namespace == ns)
1024                         {
1025                             foundPrefix = prefixDef.Name;
1026                             return true;
1027                         }
1028                         return false;
1029                     });
1030 
1031                 prefix = foundPrefix;
1032                 return foundPrefix != null;
1033             }
1034         }
1035 
1036         internal static class WsdlNamingHelper
1037         {
GetPortTypeQName(ContractDescription contract)1038             internal static XmlQualifiedName GetPortTypeQName(ContractDescription contract)
1039             {
1040                 return new XmlQualifiedName(contract.Name, contract.Namespace);
1041             }
1042 
GetBindingQName(ServiceEndpoint endpoint, WsdlExporter exporter, out bool wasUniquified)1043             internal static XmlQualifiedName GetBindingQName(ServiceEndpoint endpoint, WsdlExporter exporter, out bool wasUniquified)
1044             {
1045                 // due to problems in Sysytem.Web.Services.Descriprion.ServiceDescription.Write() (double encoding) method we cannot use encoded names for
1046                 // wsdl:binding item: we need to make sure that XmlConvert.EncodeLocalName will not find any problems with the name, and leave it unchanged.
1047                 // consider changing the name here to something that will not be encoded by XmlSerializer (GenerateSimpleXmlName()?)
1048                 string localName = endpoint.Name;
1049 
1050                 string bindingWsdlNamespace = endpoint.Binding.Namespace;
1051                 string uniquifiedLocalName = NamingHelper.GetUniqueName(localName, WsdlBindingQNameExists(exporter, bindingWsdlNamespace), null);
1052                 wasUniquified = localName != uniquifiedLocalName;
1053 
1054                 return new XmlQualifiedName(uniquifiedLocalName, bindingWsdlNamespace);
1055             }
1056 
WsdlBindingQNameExists(WsdlExporter exporter, string bindingWsdlNamespace)1057             static NamingHelper.DoesNameExist WsdlBindingQNameExists(WsdlExporter exporter, string bindingWsdlNamespace)
1058             {
1059                 return delegate(string localName, object nameCollection)
1060                 {
1061                     XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(localName, bindingWsdlNamespace);
1062                     WsdlNS.ServiceDescription wsdl = exporter.wsdlDocuments[bindingWsdlNamespace];
1063                     if (wsdl != null && wsdl.Bindings[localName] != null)
1064                         return true;
1065 
1066                     return false;
1067                 };
1068             }
1069 
1070 
1071 
GetPortName(ServiceEndpoint endpoint, WsdlNS.Service wsdlService)1072             internal static string GetPortName(ServiceEndpoint endpoint, WsdlNS.Service wsdlService)
1073             {
1074                 return NamingHelper.GetUniqueName(endpoint.Name, ServiceContainsPort(wsdlService), null);
1075             }
1076 
ServiceContainsPort(WsdlNS.Service service)1077             static NamingHelper.DoesNameExist ServiceContainsPort(WsdlNS.Service service)
1078             {
1079                 return delegate(string portName, object nameCollection)
1080                 {
1081                     foreach (WsdlNS.Port port in service.Ports)
1082                         if (port.Name == portName)
1083                             return true;
1084                     return false;
1085                 };
1086             }
1087 
GetWsdlOperationName(OperationDescription operationDescription, ContractDescription parentContractDescription)1088             internal static string GetWsdlOperationName(OperationDescription operationDescription, ContractDescription parentContractDescription)
1089             {
1090                 return operationDescription.Name;
1091             }
1092         }
1093 
1094         internal static class NetSessionHelper
1095         {
1096             internal const string NamespaceUri = "http://schemas.microsoft.com/ws/2005/12/wsdl/contract";
1097             internal const string Prefix = "msc";
1098             internal const string UsingSession = "usingSession";
1099             internal const string IsInitiating = "isInitiating";
1100             internal const string IsTerminating = "isTerminating";
1101             internal const string True = "true";
1102             internal const string False = "false";
1103 
AddUsingSessionAttributeIfNeeded(WsdlNS.PortType wsdlPortType, ContractDescription contract)1104             internal static void AddUsingSessionAttributeIfNeeded(WsdlNS.PortType wsdlPortType, ContractDescription contract)
1105             {
1106                 bool sessionValue;
1107 
1108                 if (contract.SessionMode == SessionMode.Required)
1109                 {
1110                     sessionValue = true;
1111                 }
1112                 else if (contract.SessionMode == SessionMode.NotAllowed)
1113                 {
1114                     sessionValue = false;
1115                 }
1116                 else
1117                 {
1118                     return;
1119                 }
1120 
1121                 wsdlPortType.ExtensibleAttributes = CloneAndAddToAttributes(wsdlPortType.ExtensibleAttributes, NetSessionHelper.Prefix,
1122                     NetSessionHelper.UsingSession, NetSessionHelper.NamespaceUri, ToValue(sessionValue));
1123             }
1124 
AddInitiatingTerminatingAttributesIfNeeded(WsdlNS.Operation wsdlOperation, OperationDescription operation, ContractDescription contract)1125             internal static void AddInitiatingTerminatingAttributesIfNeeded(WsdlNS.Operation wsdlOperation,
1126                 OperationDescription operation, ContractDescription contract)
1127             {
1128                 if (contract.SessionMode == SessionMode.Required)
1129                 {
1130                     AddInitiatingAttribute(wsdlOperation, operation.IsInitiating);
1131                     AddTerminatingAttribute(wsdlOperation, operation.IsTerminating);
1132                 }
1133             }
1134 
AddInitiatingAttribute(System.Web.Services.Description.Operation wsdlOperation, bool isInitiating)1135             static void AddInitiatingAttribute(System.Web.Services.Description.Operation wsdlOperation, bool isInitiating)
1136             {
1137                 wsdlOperation.ExtensibleAttributes = CloneAndAddToAttributes(wsdlOperation.ExtensibleAttributes, NetSessionHelper.Prefix,
1138                     NetSessionHelper.IsInitiating, NetSessionHelper.NamespaceUri, ToValue(isInitiating));
1139             }
1140 
AddTerminatingAttribute(System.Web.Services.Description.Operation wsdlOperation, bool isTerminating)1141             static void AddTerminatingAttribute(System.Web.Services.Description.Operation wsdlOperation, bool isTerminating)
1142             {
1143                 wsdlOperation.ExtensibleAttributes = CloneAndAddToAttributes(wsdlOperation.ExtensibleAttributes, NetSessionHelper.Prefix,
1144                     NetSessionHelper.IsTerminating, NetSessionHelper.NamespaceUri, ToValue(isTerminating));
1145             }
1146 
CloneAndAddToAttributes(XmlAttribute[] originalAttributes, string prefix, string localName, string ns, string value)1147             static XmlAttribute[] CloneAndAddToAttributes(XmlAttribute[] originalAttributes, string prefix, string localName, string ns, string value)
1148             {
1149                 XmlAttribute newAttribute = XmlDoc.CreateAttribute(prefix, localName, ns);
1150                 newAttribute.Value = value;
1151 
1152                 int originalAttributeCount = 0;
1153                 if (originalAttributes != null)
1154                     originalAttributeCount = originalAttributes.Length;
1155 
1156                 XmlAttribute[] attributes = new XmlAttribute[originalAttributeCount + 1];
1157 
1158                 if (originalAttributes != null)
1159                     originalAttributes.CopyTo(attributes, 0);
1160 
1161                 attributes[attributes.Length - 1] = newAttribute;
1162 
1163                 return attributes;
1164             }
1165 
ToValue(bool b)1166             static string ToValue(bool b)
1167             {
1168                 return b ? NetSessionHelper.True : NetSessionHelper.False;
1169             }
1170         }
1171 
CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)1172         void CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)
1173         {
1174             try
1175             {
1176                 extension.ExportContract(this, contractContext);
1177             }
1178 #pragma warning suppress 56500 // covered by FxCOP
1179             catch (Exception e)
1180             {
1181                 if (Fx.IsFatal(e))
1182                     throw;
1183                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThrowExtensionException(contractContext.Contract, extension, e));
1184             }
1185         }
1186 
CallExtension(WsdlEndpointConversionContext endpointContext, IWsdlExportExtension extension)1187         void CallExtension(WsdlEndpointConversionContext endpointContext, IWsdlExportExtension extension)
1188         {
1189             try
1190             {
1191                 extension.ExportEndpoint(this, endpointContext);
1192             }
1193 #pragma warning suppress 56500 // covered by FxCOP
1194             catch (Exception e)
1195             {
1196                 if (Fx.IsFatal(e))
1197                     throw;
1198                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThrowExtensionException(endpointContext.Endpoint, extension, e));
1199             }
1200         }
1201 
ThrowExtensionException(ContractDescription contract, IWsdlExportExtension exporter, Exception e)1202         Exception ThrowExtensionException(ContractDescription contract, IWsdlExportExtension exporter, Exception e)
1203         {
1204             string contractIdentifier = new XmlQualifiedName(contract.Name, contract.Namespace).ToString();
1205             string errorMessage = SR.GetString(SR.WsdlExtensionContractExportError, exporter.GetType(), contractIdentifier);
1206 
1207             return new InvalidOperationException(errorMessage, e);
1208         }
1209 
ThrowExtensionException(ServiceEndpoint endpoint, IWsdlExportExtension exporter, Exception e)1210         Exception ThrowExtensionException(ServiceEndpoint endpoint, IWsdlExportExtension exporter, Exception e)
1211         {
1212             string endpointIdentifier;
1213             if (endpoint.Address != null && endpoint.Address.Uri != null)
1214                 endpointIdentifier = endpoint.Address.Uri.ToString();
1215             else
1216                 endpointIdentifier = String.Format(CultureInfo.InvariantCulture,
1217                     "Contract={1}:{0} ,Binding={3}:{2}",
1218                     endpoint.Contract.Name,
1219                     endpoint.Contract.Namespace,
1220                     endpoint.Binding.Name,
1221                     endpoint.Binding.Namespace);
1222 
1223             string errorMessage = SR.GetString(SR.WsdlExtensionEndpointExportError, exporter.GetType(), endpointIdentifier);
1224 
1225             return new InvalidOperationException(errorMessage, e);
1226         }
1227 
1228         sealed class BindingDictionaryKey
1229         {
1230             public readonly ContractDescription Contract;
1231             public readonly Binding Binding;
1232 
BindingDictionaryKey(ContractDescription contract, Binding binding)1233             public BindingDictionaryKey(ContractDescription contract, Binding binding)
1234             {
1235                 this.Contract = contract;
1236                 this.Binding = binding;
1237             }
1238 
Equals(object obj)1239             public override bool Equals(object obj)
1240             {
1241                 BindingDictionaryKey key = obj as BindingDictionaryKey;
1242                 if (key != null && key.Binding == this.Binding && key.Contract == this.Contract)
1243                     return true;
1244                 return false;
1245             }
1246 
GetHashCode()1247             public override int GetHashCode()
1248             {
1249                 return this.Contract.GetHashCode() ^ this.Binding.GetHashCode();
1250             }
1251         }
1252 
1253         sealed class EndpointDictionaryKey
1254         {
1255             public readonly ServiceEndpoint Endpoint;
1256             public readonly XmlQualifiedName ServiceQName;
1257 
EndpointDictionaryKey(ServiceEndpoint endpoint, XmlQualifiedName serviceQName)1258             public EndpointDictionaryKey(ServiceEndpoint endpoint, XmlQualifiedName serviceQName)
1259             {
1260                 this.Endpoint = endpoint;
1261                 this.ServiceQName = serviceQName;
1262             }
1263 
Equals(object obj)1264             public override bool Equals(object obj)
1265             {
1266                 EndpointDictionaryKey key = obj as EndpointDictionaryKey;
1267                 if (key != null && key.Endpoint == this.Endpoint && key.ServiceQName == this.ServiceQName)
1268                     return true;
1269                 return false;
1270             }
1271 
GetHashCode()1272             public override int GetHashCode()
1273             {
1274                 return this.Endpoint.GetHashCode() ^ this.ServiceQName.GetHashCode();
1275             }
1276         }
1277     }
1278 }
1279 
1280 
1281