1 //------------------------------------------------------------------------------
2 // <copyright from='1997' to='2001' company='Microsoft Corporation'>
3 // Copyright (c) Microsoft Corporation. All Rights Reserved.
4 // Information Contained Herein is Proprietary and Confidential.
6 //------------------------------------------------------------------------------
7 namespace System.Web.Services.Description {
9 using System.Web.Services;
10 using System.Web.Services.Protocols;
12 using System.Xml.Serialization;
13 using System.Xml.Serialization.Advanced;
14 using System.Xml.Schema;
15 using System.Collections;
18 using System.Data.Design;
19 using System.Reflection;
21 using System.CodeDom.Compiler;
22 using System.Web.Services.Configuration;
23 using System.Diagnostics;
24 using System.ComponentModel;
25 using System.Security.Permissions;
26 using System.Globalization;
27 using System.Threading;
29 internal class SoapParameters {
31 ArrayList parameters = new ArrayList();
32 ArrayList inParameters = new ArrayList();
33 ArrayList outParameters = new ArrayList();
34 int checkSpecifiedCount;
35 int inCheckSpecifiedCount;
36 int outCheckSpecifiedCount;
38 internal SoapParameters(XmlMembersMapping request, XmlMembersMapping response, string[] parameterOrder, CodeIdentifiers identifiers) {
39 ArrayList requestList = new ArrayList();
40 ArrayList responseList = new ArrayList();
42 AddMappings(requestList, request);
43 if (response != null) AddMappings(responseList, response);
45 if (parameterOrder != null) {
46 for (int i = 0; i < parameterOrder.Length; i++) {
47 string elementName = parameterOrder[i];
48 XmlMemberMapping requestMapping = FindMapping(requestList, elementName);
49 SoapParameter parameter = new SoapParameter();
50 if (requestMapping != null) {
51 if (RemoveByRefMapping(responseList, requestMapping))
52 parameter.codeFlags = CodeFlags.IsByRef;
53 parameter.mapping = requestMapping;
54 requestList.Remove(requestMapping);
55 AddParameter(parameter);
58 XmlMemberMapping responseMapping = FindMapping(responseList, elementName);
59 if (responseMapping != null) {
60 parameter.codeFlags = CodeFlags.IsOut;
61 parameter.mapping = responseMapping;
62 responseList.Remove(responseMapping);
63 AddParameter(parameter);
69 foreach (XmlMemberMapping requestMapping in requestList) {
70 SoapParameter parameter = new SoapParameter();
71 if (RemoveByRefMapping(responseList, requestMapping))
72 parameter.codeFlags = CodeFlags.IsByRef;
73 parameter.mapping = requestMapping;
74 AddParameter(parameter);
77 if (responseList.Count > 0) {
78 if (!((XmlMemberMapping) responseList[0]).CheckSpecified) {
79 ret = (XmlMemberMapping)responseList[0];
80 responseList.RemoveAt(0);
82 foreach (XmlMemberMapping responseMapping in responseList) {
83 SoapParameter parameter = new SoapParameter();
84 parameter.mapping = responseMapping;
85 parameter.codeFlags = CodeFlags.IsOut;
86 AddParameter(parameter);
90 foreach (SoapParameter parameter in parameters) {
91 parameter.name = identifiers.MakeUnique(CodeIdentifier.MakeValid(parameter.mapping.MemberName));
95 void AddParameter(SoapParameter parameter) {
96 parameters.Add(parameter);
97 if (parameter.mapping.CheckSpecified) {
98 checkSpecifiedCount++;
100 if (parameter.IsByRef) {
101 inParameters.Add(parameter);
102 outParameters.Add(parameter);
103 if (parameter.mapping.CheckSpecified) {
104 inCheckSpecifiedCount++;
105 outCheckSpecifiedCount++;
107 } else if (parameter.IsOut) {
108 outParameters.Add(parameter);
109 if (parameter.mapping.CheckSpecified)
110 outCheckSpecifiedCount++;
113 inParameters.Add(parameter);
114 if (parameter.mapping.CheckSpecified)
115 inCheckSpecifiedCount++;
119 static bool RemoveByRefMapping(ArrayList responseList, XmlMemberMapping requestMapping) {
120 XmlMemberMapping responseMapping = FindMapping(responseList, requestMapping.ElementName);
121 if (responseMapping == null) return false;
122 if (requestMapping.TypeFullName != responseMapping.TypeFullName) return false;
123 if (requestMapping.Namespace != responseMapping.Namespace) return false;
124 if (requestMapping.MemberName != responseMapping.MemberName) return false;
125 responseList.Remove(responseMapping);
129 static void AddMappings(ArrayList mappingsList, XmlMembersMapping mappings) {
130 for (int i = 0; i < mappings.Count; i++) {
131 mappingsList.Add(mappings[i]);
135 static XmlMemberMapping FindMapping(ArrayList mappingsList, string elementName) {
136 foreach (XmlMemberMapping mapping in mappingsList)
137 if (mapping.ElementName == elementName)
142 internal XmlMemberMapping Return {
146 internal IList Parameters {
147 get { return parameters; }
150 internal IList InParameters {
151 get { return inParameters; }
154 internal IList OutParameters {
155 get { return outParameters; }
158 internal int CheckSpecifiedCount {
159 get { return checkSpecifiedCount; }
162 internal int InCheckSpecifiedCount {
163 get { return inCheckSpecifiedCount; }
166 internal int OutCheckSpecifiedCount {
167 get { return outCheckSpecifiedCount; }
171 internal class SoapParameter {
172 internal CodeFlags codeFlags;
173 internal string name;
174 internal XmlMemberMapping mapping;
175 internal string specifiedName;
177 internal bool IsOut {
178 get { return (codeFlags & CodeFlags.IsOut) != 0; }
181 internal bool IsByRef {
182 get { return (codeFlags & CodeFlags.IsByRef) != 0; }
185 internal static string[] GetTypeFullNames(IList parameters, int specifiedCount, CodeDomProvider codeProvider) {
186 string[] typeFullNames = new string[parameters.Count + specifiedCount];
187 GetTypeFullNames(parameters, typeFullNames, 0, specifiedCount, codeProvider);
188 return typeFullNames;
191 internal static void GetTypeFullNames(IList parameters, string[] typeFullNames, int start, int specifiedCount, CodeDomProvider codeProvider) {
193 for (int i = 0; i < parameters.Count; i++) {
194 typeFullNames[i + start + specified] = WebCodeGenerator.FullTypeName(((SoapParameter)parameters[i]).mapping, codeProvider);
195 if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
197 typeFullNames[i + start + specified] = typeof(bool).FullName;
202 internal static string[] GetNames(IList parameters, int specifiedCount) {
203 string[] names = new string[parameters.Count + specifiedCount];
204 GetNames(parameters, names, 0, specifiedCount);
208 internal static void GetNames(IList parameters, string[] names, int start, int specifiedCount) {
210 for (int i = 0; i < parameters.Count; i++) {
211 names[i + start + specified] = ((SoapParameter)parameters[i]).name;
212 if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
214 names[i + start + specified] = ((SoapParameter) parameters[i]).specifiedName;
219 internal static CodeFlags[] GetCodeFlags(IList parameters, int specifiedCount) {
220 CodeFlags[] codeFlags = new CodeFlags[parameters.Count + specifiedCount];
221 GetCodeFlags(parameters, codeFlags, 0, specifiedCount);
225 internal static void GetCodeFlags(IList parameters, CodeFlags[] codeFlags, int start, int specifiedCount) {
227 for (int i = 0; i < parameters.Count; i++) {
228 codeFlags[i + start + specified] = ((SoapParameter)parameters[i]).codeFlags;
229 if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
231 codeFlags[i + start + specified] = ((SoapParameter) parameters[i]).codeFlags;
237 internal class GlobalSoapHeader {
238 internal string fieldName;
239 internal XmlTypeMapping mapping;
240 internal bool isEncoded;
243 internal class LocalSoapHeader {
244 internal SoapHeaderDirection direction;
245 internal string fieldName;
248 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter"]/*' />
250 /// <para>[To be supplied.]</para>
252 [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
253 [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
254 public class SoapProtocolImporter : ProtocolImporter {
255 XmlSchemaImporter xmlImporter;
256 XmlCodeExporter xmlExporter;
257 SoapSchemaImporter soapImporter;
258 SoapCodeExporter soapExporter;
259 ArrayList xmlMembers = new ArrayList();
260 ArrayList soapMembers = new ArrayList();
261 Hashtable headers = new Hashtable();
262 Hashtable classHeaders = new Hashtable();
263 ArrayList propertyNames = new ArrayList();
264 ArrayList propertyValues = new ArrayList();
265 SoapExtensionImporter[] extensions;
266 SoapTransportImporter transport;
267 SoapBinding soapBinding;
268 ArrayList codeClasses = new ArrayList();
269 static TypedDataSetSchemaImporterExtension typedDataSetSchemaImporterExtension;
271 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.ProtocolName"]/*' />
273 /// <para>[To be supplied.]</para>
275 public override string ProtocolName {
276 get { return "Soap"; }
279 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.SoapBinding"]/*' />
281 /// <para>[To be supplied.]</para>
283 public SoapBinding SoapBinding {
284 get { return soapBinding; }
287 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.SoapImporter"]/*' />
289 /// <para>[To be supplied.]</para>
291 public SoapSchemaImporter SoapImporter {
292 get { return soapImporter; }
295 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.XmlImporter"]/*' />
297 /// <para>[To be supplied.]</para>
299 public XmlSchemaImporter XmlImporter {
300 get { return xmlImporter; }
303 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.XmlExporter"]/*' />
305 /// <para>[To be supplied.]</para>
307 public XmlCodeExporter XmlExporter {
308 get { return xmlExporter; }
311 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.SoapExporter"]/*' />
313 /// <para>[To be supplied.]</para>
315 public SoapCodeExporter SoapExporter {
316 get { return soapExporter; }
319 static TypedDataSetSchemaImporterExtension TypedDataSetSchemaImporterExtension {
321 if (typedDataSetSchemaImporterExtension == null) {
322 typedDataSetSchemaImporterExtension = new TypedDataSetSchemaImporterExtension();
324 return typedDataSetSchemaImporterExtension;
328 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.BeginNamespace"]/*' />
330 /// <para>[To be supplied.]</para>
332 protected override void BeginNamespace() {
335 ExtraCodeClasses.Clear();
336 soapImporter = new SoapSchemaImporter(AbstractSchemas, ServiceImporter.CodeGenerationOptions, ImportContext);
337 xmlImporter = new XmlSchemaImporter(ConcreteSchemas, ServiceImporter.CodeGenerationOptions, ServiceImporter.CodeGenerator, ImportContext);
338 foreach (Type extensionType in ServiceImporter.Extensions) {
339 xmlImporter.Extensions.Add(extensionType.FullName, extensionType);
341 // use cached version of typed DataSetSchemaImporterExtension for /sharetypes feature
343 xmlImporter.Extensions.Add(TypedDataSetSchemaImporterExtension);
344 xmlImporter.Extensions.Add(new DataSetSchemaImporterExtension());
345 xmlExporter = new XmlCodeExporter(this.CodeNamespace, ServiceImporter.CodeCompileUnit, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
346 soapExporter = new SoapCodeExporter(this.CodeNamespace, null, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
348 catch (Exception e) {
349 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
352 throw new InvalidOperationException(Res.GetString(Res.InitFailed), e);
356 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.EndNamespace"]/*' />
358 /// <para>[To be supplied.]</para>
360 protected override void EndNamespace() {
361 // need to preprocess all exported schemas to make sure that IXmlSerializable schemas are Merged and the resulting set is valid
362 ConcreteSchemas.Compile(null, false);
364 foreach (GlobalSoapHeader soapHeader in headers.Values) {
365 if (soapHeader.isEncoded)
366 soapExporter.ExportTypeMapping(soapHeader.mapping);
368 xmlExporter.ExportTypeMapping(soapHeader.mapping);
371 foreach (XmlMembersMapping member in xmlMembers)
372 xmlExporter.ExportMembersMapping(member);
374 foreach (XmlMembersMapping member in soapMembers)
375 soapExporter.ExportMembersMapping(member);
377 // NOTE, Microsoft, we are sharing the SoapInclude and XmlInclude attributes of the
378 // class among ALL classes generated, This is probably OK, since doing to per
379 // class would probably result in the same set of includes if the user
380 // has object as a return value (meaning 'all' types are OK).
381 foreach (CodeTypeDeclaration codeClass in codeClasses) {
382 foreach (CodeAttributeDeclaration attribute in xmlExporter.IncludeMetadata) {
383 codeClass.CustomAttributes.Add(attribute);
385 foreach (CodeAttributeDeclaration attribute in soapExporter.IncludeMetadata) {
386 codeClass.CustomAttributes.Add(attribute);
389 foreach (CodeTypeDeclaration declaration in ExtraCodeClasses) {
390 this.CodeNamespace.Types.Add(declaration);
392 CodeGenerator.ValidateIdentifiers(CodeNamespace);
395 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.IsBindingSupported"]/*' />
397 /// <para>[To be supplied.]</para>
399 protected override bool IsBindingSupported() {
400 SoapBinding soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding));
401 if (soapBinding == null || soapBinding.GetType() != typeof(SoapBinding)) return false;
403 if (GetTransport(soapBinding.Transport) == null) {
404 UnsupportedBindingWarning(Res.GetString(Res.ThereIsNoSoapTransportImporterThatUnderstands1, soapBinding.Transport));
411 internal SoapTransportImporter GetTransport(string transport) {
412 foreach (Type type in WebServicesSection.Current.SoapTransportImporters)
414 SoapTransportImporter transportImporter = (SoapTransportImporter)Activator.CreateInstance(type);
415 transportImporter.ImportContext = this;
416 if (transportImporter.IsSupportedTransport(transport)) return transportImporter;
421 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.BeginClass"]/*' />
423 /// <para>[To be supplied.]</para>
425 protected override CodeTypeDeclaration BeginClass() {
428 soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding));
429 transport = GetTransport(soapBinding.Transport);
431 Type[] requiredTypes = new Type[] { typeof(SoapDocumentMethodAttribute), typeof(XmlAttributeAttribute), typeof(WebService), typeof(Object), typeof(DebuggerStepThroughAttribute), typeof(DesignerCategoryAttribute) };
432 WebCodeGenerator.AddImports(this.CodeNamespace, WebCodeGenerator.GetNamespacesForTypes(requiredTypes));
434 if (Style == ServiceDescriptionImportStyle.Server)
435 flags = CodeFlags.IsAbstract;
436 else if (Style == ServiceDescriptionImportStyle.ServerInterface)
437 flags = CodeFlags.IsInterface;
438 CodeTypeDeclaration codeClass = WebCodeGenerator.CreateClass(this.ClassName, null,
439 new string[0], null, CodeFlags.IsPublic | flags,
440 ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes));
442 codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
443 if (Style == ServiceDescriptionImportStyle.Client) {
444 codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DebuggerStepThroughAttribute).FullName));
445 codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DesignerCategoryAttribute).FullName, new CodeAttributeArgument[] { new CodeAttributeArgument(new CodePrimitiveExpression("code")) }));
447 else if (Style == ServiceDescriptionImportStyle.Server) {
448 CodeAttributeDeclaration webService = new CodeAttributeDeclaration(typeof(WebServiceAttribute).FullName);
449 string targetNs = Service != null ? Service.ServiceDescription.TargetNamespace : Binding.ServiceDescription.TargetNamespace;
450 webService.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(targetNs)));
451 codeClass.CustomAttributes.Add(webService);
454 CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(typeof(WebServiceBindingAttribute).FullName);
455 attribute.Arguments.Add(new CodeAttributeArgument("Name", new CodePrimitiveExpression(XmlConvert.DecodeName(Binding.Name))));
456 attribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(Binding.ServiceDescription.TargetNamespace)));
458 codeClass.CustomAttributes.Add(attribute);
460 codeClasses.Add(codeClass);
461 classHeaders.Clear();
465 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.EndClass"]/*' />
467 /// <para>[To be supplied.]</para>
469 protected override void EndClass() {
470 if (transport != null)
471 transport.ImportClass();
475 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.IsOperationFlowSupported"]/*' />
477 /// <para>[To be supplied.]</para>
479 protected override bool IsOperationFlowSupported(OperationFlow flow) {
480 return flow == OperationFlow.OneWay || flow == OperationFlow.RequestResponse;
483 void BeginMetadata() {
484 propertyNames.Clear();
485 propertyValues.Clear();
488 bool MetadataPropertiesAdded {
489 get { return propertyNames.Count > 0; }
492 void AddMetadataProperty(string name, object value) {
493 AddMetadataProperty(name, new CodePrimitiveExpression(value));
496 void AddMetadataProperty(string name, CodeExpression expr) {
497 propertyNames.Add(name);
498 propertyValues.Add(expr);
501 void EndMetadata(CodeAttributeDeclarationCollection metadata, Type attributeType, string parameter) {
502 CodeExpression[] parameters;
503 if (parameter == null) {
504 parameters = new CodeExpression[0];
507 parameters = new CodeExpression[1] { new CodePrimitiveExpression(parameter) };
509 WebCodeGenerator.AddCustomAttribute(metadata, attributeType, parameters,
510 (string[])propertyNames.ToArray(typeof(string)),
511 (CodeExpression[])propertyValues.ToArray(typeof(CodeExpression)));
514 void GenerateExtensionMetadata(CodeAttributeDeclarationCollection metadata) {
515 if (extensions == null) {
516 TypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionImporterTypes;
517 extensions = new SoapExtensionImporter[extensionTypes.Count];
518 for (int i = 0; i < extensions.Length; i++) {
519 SoapExtensionImporter extension = (SoapExtensionImporter)Activator.CreateInstance(extensionTypes[i].Type);
520 extension.ImportContext = this;
521 extensions[i] = extension;
524 foreach (SoapExtensionImporter extension in extensions) {
525 extension.ImportMethod(metadata);
529 void PrepareHeaders(MessageBinding messageBinding) {
530 // By default, map all headers to properties on the generated class
531 // ExtensionImporters can modify this behavior by clearing the flag
532 SoapHeaderBinding[] headers = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding));
533 foreach (SoapHeaderBinding header in headers) {
534 header.MapToProperty = true;
538 void GenerateHeaders(CodeAttributeDeclarationCollection metadata, SoapBindingUse use, bool rpc, MessageBinding requestMessage, MessageBinding responseMessage) {
539 Hashtable localHeaders = new Hashtable();
541 for (int i = 0; i < 2; ++i) {
542 MessageBinding messageBinding;
543 SoapHeaderDirection direction;
545 messageBinding = requestMessage;
546 direction = SoapHeaderDirection.In;
548 else if (responseMessage != null) {
549 messageBinding = responseMessage;
550 direction = SoapHeaderDirection.Out;
555 SoapHeaderBinding[] headerBindings = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding));
556 foreach (SoapHeaderBinding header in headerBindings) {
557 // Skip headers which should not be mapped to properties (extension importers can control this)
558 if (!header.MapToProperty) continue;
560 if (use != header.Use) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionHeaderAndBodyUseMismatch));
561 if (use == SoapBindingUse.Encoded && !IsSoapEncodingPresent(header.Encoding) )
562 throw new InvalidOperationException(Res.GetString(Res.WebUnknownEncodingStyle, header.Encoding));
564 Message message = ServiceDescriptions.GetMessage(header.Message);
565 if (message == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessage2, header.Message.Name, header.Message.Namespace));
567 MessagePart part = message.FindPartByName(header.Part);
568 if (part == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessagePartForMessageFromNamespace3, part.Name, header.Message.Name, header.Message.Namespace));
570 XmlTypeMapping mapping;
572 if (use == SoapBindingUse.Encoded) {
573 if (part.Type.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartTypeRequired, part.Name, header.Message.Name, header.Message.Namespace));
574 if (!part.Element.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartElementWarning, part.Name, header.Message.Name, header.Message.Namespace));
575 mapping = soapImporter.ImportDerivedTypeMapping(part.Type, typeof(SoapHeader), true);
576 key = "type=" + part.Type.ToString();
579 if (part.Element.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartElementRequired, part.Name, header.Message.Name, header.Message.Namespace));
580 if (!part.Type.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartTypeWarning, part.Name, header.Message.Name, header.Message.Namespace));
581 mapping = xmlImporter.ImportDerivedTypeMapping(part.Element, typeof(SoapHeader), true);
582 key = "element=" + part.Element.ToString();
584 LocalSoapHeader localHeader = (LocalSoapHeader)localHeaders[key];
585 if (localHeader == null) {
586 GlobalSoapHeader globalHeader = (GlobalSoapHeader)classHeaders[key];
587 if (globalHeader == null) {
588 globalHeader = new GlobalSoapHeader();
589 globalHeader.isEncoded = use == SoapBindingUse.Encoded;
590 string fieldName = CodeIdentifier.MakeValid(mapping.ElementName);
591 if (fieldName == mapping.TypeName) fieldName += "Value";
592 fieldName = MethodNames.AddUnique(fieldName, mapping);
593 globalHeader.fieldName = fieldName;
594 WebCodeGenerator.AddMember(CodeTypeDeclaration, mapping.TypeFullName, globalHeader.fieldName, null, null, CodeFlags.IsPublic, ServiceImporter.CodeGenerationOptions);
595 globalHeader.mapping = mapping;
596 classHeaders.Add(key, globalHeader);
597 if (headers[key] == null)
598 headers.Add(key, globalHeader);
601 localHeader = new LocalSoapHeader();
602 localHeader.fieldName = globalHeader.fieldName;
603 localHeader.direction = direction;
604 localHeaders.Add(key, localHeader);
607 if (localHeader.direction != direction)
608 localHeader.direction = SoapHeaderDirection.InOut;
613 foreach (LocalSoapHeader soapHeader in localHeaders.Values) {
615 if (soapHeader.direction == SoapHeaderDirection.Out) {
616 AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.Out.ToString()));
618 else if (soapHeader.direction == SoapHeaderDirection.InOut) {
619 AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.InOut.ToString()));
622 EndMetadata(metadata, typeof(SoapHeaderAttribute), soapHeader.fieldName);
626 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.GenerateMethod"]/*' />
628 /// <para>[To be supplied.]</para>
630 protected override CodeMemberMethod GenerateMethod() {
631 Message requestMessage;
632 Message responseMessage;
633 string[] parameterOrder;
634 SoapBodyBinding soapRequestBinding;
635 SoapBodyBinding soapResponseBinding;
636 MessageBinding requestBinding;
637 MessageBinding responseBinding;
639 SoapOperationBinding soapOperationBinding = (SoapOperationBinding)this.OperationBinding.Extensions.Find(typeof(SoapOperationBinding));
640 if (soapOperationBinding == null) throw OperationBindingSyntaxException(Res.GetString(Res.MissingSoapOperationBinding0));
642 SoapBindingStyle soapBindingStyle = soapOperationBinding.Style;
643 if (soapBindingStyle == SoapBindingStyle.Default)
644 soapBindingStyle = SoapBinding.Style;
645 if (soapBindingStyle == SoapBindingStyle.Default)
646 soapBindingStyle = SoapBindingStyle.Document;
648 parameterOrder = this.Operation.ParameterOrder;
650 requestMessage = this.InputMessage;
651 requestBinding = this.OperationBinding.Input;
652 soapRequestBinding = (SoapBodyBinding)this.OperationBinding.Input.Extensions.Find(typeof(SoapBodyBinding));
653 if (soapRequestBinding == null) {
654 UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyInputBinding0));
658 if (this.Operation.Messages.Output != null) {
659 responseMessage = this.OutputMessage;
660 responseBinding = this.OperationBinding.Output;
661 soapResponseBinding = (SoapBodyBinding)this.OperationBinding.Output.Extensions.Find(typeof(SoapBodyBinding));
662 if (soapResponseBinding == null) {
663 UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyOutputBinding0));
668 responseMessage = null;
669 responseBinding = null;
670 soapResponseBinding = null;
673 CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
675 PrepareHeaders(requestBinding);
676 if (responseBinding != null) PrepareHeaders(responseBinding);
678 string requestMessageName;
679 string responseMessageName = null;
681 requestMessageName = !String.IsNullOrEmpty(requestBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? requestBinding.Name : this.Operation.Name; // per WSDL 1.1 sec 3.5
682 requestMessageName = XmlConvert.DecodeName(requestMessageName);
684 if (responseBinding != null) {
685 responseMessageName = !String.IsNullOrEmpty(responseBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? responseBinding.Name : this.Operation.Name + "Response"; // per WSDL 1.1 sec 3.5
686 responseMessageName = XmlConvert.DecodeName(responseMessageName);
689 GenerateExtensionMetadata(metadata);
690 GenerateHeaders(metadata, soapRequestBinding.Use, soapBindingStyle == SoapBindingStyle.Rpc, requestBinding, responseBinding);
692 MessagePart[] requestParts = GetMessageParts(requestMessage, soapRequestBinding);
694 if (!CheckMessageStyles(MethodName, requestParts, soapRequestBinding, soapBindingStyle, out hasWrapper))
697 MessagePart[] responseParts = null;
698 if (responseMessage != null) {
699 responseParts = GetMessageParts(responseMessage, soapResponseBinding);
700 bool responseHasWrapper;
701 if (!CheckMessageStyles(MethodName, responseParts, soapResponseBinding, soapBindingStyle, out responseHasWrapper))
704 // since we're using a potentially inaccurate heuristic to determine whether there's a wrapper,
705 // if we disagree about the request and response we should assume there isn't a wrapper.
706 if (hasWrapper != responseHasWrapper)
710 bool wrapperNamesMatter = (soapBindingStyle != SoapBindingStyle.Rpc && hasWrapper) || (soapRequestBinding.Use == SoapBindingUse.Literal && soapBindingStyle == SoapBindingStyle.Rpc);
712 XmlMembersMapping request = ImportMessage(requestMessageName, requestParts, soapRequestBinding, soapBindingStyle, hasWrapper);
713 if (request == null) return null;
715 XmlMembersMapping response = null;
717 if (responseMessage != null) {
718 response = ImportMessage(responseMessageName, responseParts, soapResponseBinding, soapBindingStyle, hasWrapper);
719 if (response == null) return null;
722 string methodName = CodeIdentifier.MakeValid(XmlConvert.DecodeName(this.Operation.Name));
723 if (ClassName == methodName) {
724 methodName = "Call" + methodName;
726 string uniqueMethodName = MethodNames.AddUnique(CodeIdentifier.MakeValid(XmlConvert.DecodeName(methodName)), this.Operation);
727 bool differentNames = methodName != uniqueMethodName;
729 CodeIdentifiers localIdentifiers = new CodeIdentifiers(false);
730 localIdentifiers.AddReserved(uniqueMethodName);
732 SoapParameters parameters = new SoapParameters(request, response, parameterOrder, MethodNames);
734 foreach (SoapParameter param in parameters.Parameters) {
735 if ((param.IsOut || param.IsByRef) && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReferenceParameters)) {
736 UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReferenceParameters, ServiceImporter.CodeGenerator.GetType().Name));
739 param.name = localIdentifiers.AddUnique(param.name, null);
740 if (param.mapping.CheckSpecified)
741 param.specifiedName = localIdentifiers.AddUnique(param.name + "Specified", null);
744 if (!(Style == ServiceDescriptionImportStyle.Client) || differentNames) {
746 if (differentNames) AddMetadataProperty("MessageName", uniqueMethodName);
747 EndMetadata(metadata, typeof(WebMethodAttribute), null);
751 if (wrapperNamesMatter && request.ElementName.Length > 0 && request.ElementName != uniqueMethodName)
752 AddMetadataProperty("RequestElementName", request.ElementName);
753 if (request.Namespace != null)
754 AddMetadataProperty("RequestNamespace", request.Namespace);
755 if (response == null) {
756 AddMetadataProperty("OneWay", true);
759 if (wrapperNamesMatter && response.ElementName.Length > 0 && response.ElementName != (uniqueMethodName + "Response"))
760 AddMetadataProperty("ResponseElementName", response.ElementName);
761 if (response.Namespace != null)
762 AddMetadataProperty("ResponseNamespace", response.Namespace);
765 if (soapBindingStyle == SoapBindingStyle.Rpc) {
766 if (soapRequestBinding.Use != SoapBindingUse.Encoded) {
767 AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G")));
769 EndMetadata(metadata, typeof(SoapRpcMethodAttribute), soapOperationBinding.SoapAction);
772 AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G")));
773 AddMetadataProperty("ParameterStyle", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapParameterStyle).FullName), Enum.Format(typeof(SoapParameterStyle), hasWrapper ? SoapParameterStyle.Wrapped : SoapParameterStyle.Bare, "G")));
774 EndMetadata(metadata, typeof(SoapDocumentMethodAttribute), soapOperationBinding.SoapAction);
776 IsEncodedBinding = IsEncodedBinding || (soapRequestBinding.Use == SoapBindingUse.Encoded);
778 CodeAttributeDeclarationCollection[] paramsMetadata = new CodeAttributeDeclarationCollection[parameters.Parameters.Count + parameters.CheckSpecifiedCount];
780 CodeAttributeDeclaration ignoreAttribute = new CodeAttributeDeclaration(typeof(XmlIgnoreAttribute).FullName);
781 foreach (SoapParameter parameter in parameters.Parameters) {
782 paramsMetadata[j] = new CodeAttributeDeclarationCollection();
783 if (soapRequestBinding.Use == SoapBindingUse.Encoded)
784 soapExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, parameter.name != parameter.mapping.MemberName);
786 string ns = soapBindingStyle == SoapBindingStyle.Rpc ? parameter.mapping.Namespace : parameter.IsOut ? response.Namespace : request.Namespace;
787 bool forceUseMemberName = parameter.name != parameter.mapping.MemberName;
788 xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, ns, forceUseMemberName);
789 if (parameter.mapping.CheckSpecified) {
791 paramsMetadata[j] = new CodeAttributeDeclarationCollection();
792 xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, ns, parameter.specifiedName != parameter.mapping.MemberName + "Specified");
793 paramsMetadata[j].Add(ignoreAttribute);
796 if (paramsMetadata[j].Count > 0 && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ParameterAttributes)) {
797 UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportParameterAttributes, ServiceImporter.CodeGenerator.GetType().Name));
803 CodeFlags[] parameterFlags = SoapParameter.GetCodeFlags(parameters.Parameters, parameters.CheckSpecifiedCount);
804 string[] parameterTypes = SoapParameter.GetTypeFullNames(parameters.Parameters, parameters.CheckSpecifiedCount, ServiceImporter.CodeGenerator);
805 string returnType = parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator);
807 CodeMemberMethod mainCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, methodName,
810 SoapParameter.GetNames(parameters.Parameters, parameters.CheckSpecifiedCount),
814 CodeFlags.IsPublic | (Style == ServiceDescriptionImportStyle.Client ? 0 : CodeFlags.IsAbstract));
816 mainCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
818 if (parameters.Return != null) {
819 if (soapRequestBinding.Use == SoapBindingUse.Encoded)
820 soapExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, parameters.Return.ElementName != uniqueMethodName + "Result");
822 xmlExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, response.Namespace, parameters.Return.ElementName != uniqueMethodName + "Result");
824 if (mainCodeMethod.ReturnTypeCustomAttributes.Count != 0 && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReturnTypeAttributes)) {
825 UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReturnTypeAttributes, ServiceImporter.CodeGenerator.GetType().Name));
830 string resultsName = localIdentifiers.MakeUnique("results");
832 if (Style == ServiceDescriptionImportStyle.Client) {
833 bool oldAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateOldAsync) != 0;
834 bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 &&
835 ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) &&
836 ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates);
837 CodeExpression[] invokeParams = new CodeExpression[2];
838 CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
839 CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Invoke", invokeParams);
840 WriteReturnMappings(mainCodeMethod, invoke, parameters, resultsName);
843 int inCount = parameters.InParameters.Count + parameters.InCheckSpecifiedCount;
845 string[] asyncParameterTypes = new string[inCount + 2];
846 SoapParameter.GetTypeFullNames(parameters.InParameters, asyncParameterTypes, 0, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator);
847 asyncParameterTypes[inCount] = typeof(AsyncCallback).FullName;
848 asyncParameterTypes[inCount + 1] = typeof(object).FullName;
850 string[] asyncParameterNames = new string[inCount + 2];
851 SoapParameter.GetNames(parameters.InParameters, asyncParameterNames, 0, parameters.InCheckSpecifiedCount);
852 asyncParameterNames[inCount] = "callback";
853 asyncParameterNames[inCount + 1] = "asyncState";
855 CodeFlags[] asyncParameterFlags = new CodeFlags[inCount + 2];
857 CodeMemberMethod beginCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "Begin" + uniqueMethodName,
861 typeof(IAsyncResult).FullName,
865 beginCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
867 invokeParams = new CodeExpression[4];
868 CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
869 invokeParams[2] = new CodeArgumentReferenceExpression("callback");
870 invokeParams[3] = new CodeArgumentReferenceExpression("asyncState");
872 invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "BeginInvoke", invokeParams);
873 beginCodeMethod.Statements.Add(new CodeMethodReturnStatement(invoke));
875 int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
876 string[] asyncReturnTypes = new string[outCount + 1];
877 SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
878 asyncReturnTypes[0] = typeof(IAsyncResult).FullName;
880 string[] asyncReturnNames = new string[outCount + 1];
881 SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount);
882 asyncReturnNames[0] = "asyncResult";
884 CodeFlags[] asyncReturnFlags = new CodeFlags[outCount + 1];
885 for (int i = 0; i < outCount; i++)
886 asyncReturnFlags[i + 1] = CodeFlags.IsOut;
888 CodeMemberMethod codeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "End" + uniqueMethodName,
892 parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator),
896 codeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
898 CodeExpression invokeParam = new CodeArgumentReferenceExpression("asyncResult");
899 invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "EndInvoke", new CodeExpression[] { invokeParam });
901 WriteReturnMappings(codeMethod, invoke, parameters, resultsName);
904 // new RAD Async pattern
906 string methodKey = MethodSignature(uniqueMethodName, returnType, parameterFlags, parameterTypes);
907 DelegateInfo delegateInfo = (DelegateInfo)ExportContext[methodKey];
908 if (delegateInfo == null) {
909 string handlerType = ClassNames.AddUnique(uniqueMethodName + "CompletedEventHandler", uniqueMethodName);
910 string handlerArgs = ClassNames.AddUnique(uniqueMethodName + "CompletedEventArgs", uniqueMethodName);
911 delegateInfo = new DelegateInfo(handlerType, handlerArgs);
913 string handlerName = MethodNames.AddUnique(uniqueMethodName + "Completed", uniqueMethodName);
914 string asyncName = MethodNames.AddUnique(uniqueMethodName + "Async", uniqueMethodName);
915 string callbackMember = MethodNames.AddUnique(uniqueMethodName + "OperationCompleted", uniqueMethodName);
916 string callbackName = MethodNames.AddUnique("On" + uniqueMethodName + "OperationCompleted", uniqueMethodName);
918 // public event xxxCompletedEventHandler xxxCompleted;
919 WebCodeGenerator.AddEvent(this.CodeTypeDeclaration.Members, delegateInfo.handlerType, handlerName);
921 // private SendOrPostCallback xxxOperationCompleted;
922 WebCodeGenerator.AddCallbackDeclaration(this.CodeTypeDeclaration.Members, callbackMember);
924 // create the pair of xxxAsync methods
925 string[] inParamNames = SoapParameter.GetNames(parameters.InParameters, parameters.InCheckSpecifiedCount);
926 string userState = UniqueName("userState", inParamNames);
927 CodeMemberMethod asyncCodeMethod = WebCodeGenerator.AddAsyncMethod(this.CodeTypeDeclaration, asyncName,
928 SoapParameter.GetTypeFullNames(parameters.InParameters, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator), inParamNames, callbackMember, callbackName, userState);
930 // Generate InvokeAsync call
931 invokeParams = new CodeExpression[4];
932 CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
933 invokeParams[2] = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), callbackMember);
934 invokeParams[3] = new CodeArgumentReferenceExpression(userState);
936 invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InvokeAsync", invokeParams);
937 asyncCodeMethod.Statements.Add(invoke);
939 // private void On_xxx_OperationCompleted(object arg) {..}
940 bool methodHasOutParameters = parameters.Return != null || parameters.OutParameters.Count > 0;
941 WebCodeGenerator.AddCallbackImplementation(this.CodeTypeDeclaration, callbackName, handlerName, delegateInfo.handlerArgs, methodHasOutParameters);
943 if (ExportContext[methodKey] == null) {
944 // public delegate void xxxCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs args);
945 WebCodeGenerator.AddDelegate(ExtraCodeClasses, delegateInfo.handlerType, methodHasOutParameters ? delegateInfo.handlerArgs : typeof(AsyncCompletedEventArgs).FullName);
947 // Create strongly-typed Args class
948 if (methodHasOutParameters) {
949 int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
950 string[] asyncReturnTypes = new string[outCount + 1];
951 SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
952 asyncReturnTypes[0] = parameters.Return == null ? null : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator);
954 string[] asyncReturnNames = new string[outCount + 1];
955 SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount);
956 asyncReturnNames[0] = parameters.Return == null ? null : "Result";
957 ExtraCodeClasses.Add(WebCodeGenerator.CreateArgsClass(delegateInfo.handlerArgs, asyncReturnTypes, asyncReturnNames, ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)));
959 ExportContext[methodKey] = delegateInfo;
963 return mainCodeMethod;
966 void WriteReturnMappings(CodeMemberMethod codeMethod, CodeExpression invoke, SoapParameters parameters, string resultsName) {
967 if (parameters.Return == null && parameters.OutParameters.Count == 0) {
968 codeMethod.Statements.Add(new CodeExpressionStatement(invoke));
971 codeMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), resultsName, invoke));
973 int count = parameters.Return == null ? 0 : 1;
974 for (int i = 0; i < parameters.OutParameters.Count; i++) {
975 SoapParameter parameter = (SoapParameter)parameters.OutParameters[i];
976 CodeExpression target = new CodeArgumentReferenceExpression(parameter.name);
977 CodeExpression value = new CodeArrayIndexerExpression();
978 ((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
979 ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++));
980 value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameter.mapping, ServiceImporter.CodeGenerator), value);
981 codeMethod.Statements.Add(new CodeAssignStatement(target, value));
982 if (parameter.mapping.CheckSpecified) {
983 target = new CodeArgumentReferenceExpression(parameter.name + "Specified");
984 value = new CodeArrayIndexerExpression();
985 ((CodeArrayIndexerExpression) value).TargetObject = new CodeVariableReferenceExpression(resultsName);
986 ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++));
987 value = new CodeCastExpression(typeof(bool).FullName, value);
988 codeMethod.Statements.Add(new CodeAssignStatement(target, value));
992 if (parameters.Return != null) {
993 CodeExpression value = new CodeArrayIndexerExpression();
994 ((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
995 ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(0));
996 value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator), value);
997 codeMethod.Statements.Add(new CodeMethodReturnStatement(value));
1002 void CreateInvokeParams(CodeExpression[] invokeParams, string methodName, IList parameters, int checkSpecifiedCount) {
1003 invokeParams[0] = new CodePrimitiveExpression(methodName);
1005 CodeExpression[] values = new CodeExpression[parameters.Count + checkSpecifiedCount];
1007 for (int i = 0; i < parameters.Count; i++) {
1008 SoapParameter parameter = (SoapParameter)parameters[i];
1009 values[value++] = new CodeArgumentReferenceExpression(parameter.name);
1010 if (parameter.mapping.CheckSpecified)
1011 values[value++] = new CodeArgumentReferenceExpression(parameter.specifiedName);
1013 invokeParams[1] = new CodeArrayCreateExpression(typeof(object).FullName, values);
1016 // returns false if we didn't like the message -- otherwise caller is safe to use body binding and binding style
1017 bool CheckMessageStyles(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, out bool hasWrapper) {
1019 if (soapBodyBinding.Use == SoapBindingUse.Default) {
1020 soapBodyBinding.Use = SoapBindingUse.Literal;
1022 if (soapBodyBinding.Use == SoapBindingUse.Literal) {
1023 if (soapBindingStyle == SoapBindingStyle.Rpc) {
1024 foreach (MessagePart part in parts) {
1025 if (!part.Element.IsEmpty) {
1026 UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInRpcUseLiteralMessageMustSpecify0));
1032 if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
1033 // special top-level any case
1034 if (!parts[0].Element.IsEmpty) {
1035 UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
1038 XmlMembersMapping membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
1039 if (membersMapping == null) {
1040 UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIsAny, parts[0].Type.Name, parts[0].Type.Namespace));
1046 foreach (MessagePart part in parts) {
1047 if (!part.Type.IsEmpty) {
1048 UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
1051 if (part.Element.IsEmpty) {
1052 UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAUseLiteralMessageMustSpecify0));
1058 else if (soapBodyBinding.Use == SoapBindingUse.Encoded) {
1059 if (!IsSoapEncodingPresent(soapBodyBinding.Encoding)) {
1060 UnsupportedOperationBindingWarning(Res.GetString(Res.TheEncodingIsNotSupported1, soapBodyBinding.Encoding));
1063 foreach (MessagePart part in parts) {
1064 if (!part.Element.IsEmpty) {
1065 UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingAnElementForUseEncodedMessageParts0));
1068 if (part.Type.IsEmpty) {
1069 UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAnUseEncodedMessageMustSpecify0));
1075 if (soapBindingStyle == SoapBindingStyle.Rpc) {
1078 else if (soapBindingStyle == SoapBindingStyle.Document) {
1079 // NOTE, Microsoft. WSDL doesn't really let us figure out whether a document is
1080 // in fact a struct containing parameters, so we apply a little heuristic here
1081 // in order to produce the appropriate programming model.
1082 hasWrapper = (parts.Length == 1 && string.Compare(parts[0].Name, "parameters", StringComparison.Ordinal) == 0);
1088 /// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.IsSoapEncodingPresent"]/*' />
1090 protected virtual bool IsSoapEncodingPresent(string uriList) {
1093 iStart = uriList.IndexOf(Soap.Encoding, iStart, StringComparison.Ordinal);
1096 int iEnd = iStart + Soap.Encoding.Length;
1097 if (iStart == 0 || uriList[iStart - 1] == ' ')
1098 if (iEnd == uriList.Length || uriList[iEnd] == ' ')
1101 } while (iStart < uriList.Length);
1105 MessagePart[] GetMessageParts(Message message, SoapBodyBinding soapBodyBinding) {
1106 MessagePart[] parts;
1107 if (soapBodyBinding.Parts == null) {
1108 parts = new MessagePart[message.Parts.Count];
1109 message.Parts.CopyTo(parts, 0);
1112 parts = message.FindPartsByName(soapBodyBinding.Parts);
1117 XmlMembersMapping ImportMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) {
1118 if (soapBodyBinding.Use == SoapBindingUse.Encoded)
1119 return ImportEncodedMessage(messageName, parts, soapBodyBinding, wrapped);
1121 return ImportLiteralMessage(messageName, parts, soapBodyBinding, soapBindingStyle, wrapped);
1124 XmlMembersMapping ImportEncodedMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, bool wrapped) {
1125 XmlMembersMapping membersMapping;
1127 SoapSchemaMember schemaMember = new SoapSchemaMember();
1128 schemaMember.MemberName = parts[0].Name;
1129 schemaMember.MemberType = parts[0].Type;
1130 membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMember);
1133 SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length];
1134 for (int i = 0; i < schemaMembers.Length; i++) {
1135 MessagePart part = parts[i];
1136 SoapSchemaMember schemaMember = new SoapSchemaMember();
1137 schemaMember.MemberName = part.Name;
1138 schemaMember.MemberType = part.Type;
1139 schemaMembers[i] = schemaMember;
1141 membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers);
1143 soapMembers.Add(membersMapping);
1144 return membersMapping;
1147 XmlMembersMapping ImportLiteralMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) {
1148 XmlMembersMapping membersMapping;
1149 if (soapBindingStyle == SoapBindingStyle.Rpc) {
1150 SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length];
1151 for (int i = 0; i < schemaMembers.Length; i++) {
1152 MessagePart part = parts[i];
1153 SoapSchemaMember schemaMember = new SoapSchemaMember();
1154 schemaMember.MemberName = part.Name;
1155 schemaMember.MemberType = part.Type;
1156 schemaMembers[i] = schemaMember;
1158 membersMapping = xmlImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers);
1161 membersMapping = xmlImporter.ImportMembersMapping(parts[0].Element);
1164 if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
1165 // special case for <any> at root
1166 // we know this will work because we tried it earlier in CheckMessageStyles.
1167 membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
1168 xmlMembers.Add(membersMapping);
1169 return membersMapping;
1171 XmlQualifiedName[] names = new XmlQualifiedName[parts.Length];
1172 for (int i = 0; i < parts.Length; i++)
1173 names[i] = parts[i].Element;
1174 membersMapping = xmlImporter.ImportMembersMapping(names);
1176 xmlMembers.Add(membersMapping);
1177 return membersMapping;