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