New test.
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / Methods.cs
1 //
2 // Methods.cs: Information about a method and its mapping to a SOAP web service.
3 //
4 // Author:
5 //   Miguel de Icaza
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // (C) 2003 Ximian, Inc.
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Reflection;
33 using System.Collections;
34 using System.Xml;
35 using System.Xml.Serialization;
36 using System.Web.Services;
37 using System.Web.Services.Description;
38
39 namespace System.Web.Services.Protocols {
40
41         //
42         // This class represents all the information we extract from a MethodInfo
43         // in the SoapHttpClientProtocol derivative stub class
44         //
45         internal class SoapMethodStubInfo : MethodStubInfo
46         {
47                 internal string Action;
48                 internal string Binding;
49
50                 // The name/namespace of the request 
51                 internal string RequestName;
52                 internal string RequestNamespace;
53
54                 // The name/namespace of the response.
55                 internal string ResponseName;
56                 internal string ResponseNamespace;
57                 
58                 internal bool OneWay;
59                 internal SoapParameterStyle ParameterStyle;
60                 internal SoapBindingStyle SoapBindingStyle;
61                 internal SoapBindingUse Use;
62
63                 internal HeaderInfo[] Headers;
64                 internal HeaderInfo[] InHeaders;
65                 internal HeaderInfo[] OutHeaders;
66                 internal HeaderInfo[] FaultHeaders;
67                 internal SoapExtensionRuntimeConfig[] SoapExtensions;
68                 
69                 internal XmlMembersMapping InputMembersMapping;
70                 internal XmlMembersMapping OutputMembersMapping;
71                 internal XmlMembersMapping InputHeaderMembersMapping;
72                 internal XmlMembersMapping OutputHeaderMembersMapping;
73                 internal XmlMembersMapping FaultHeaderMembersMapping;
74                 
75                 private int requestSerializerId;
76                 private int responseSerializerId;
77                 private int requestHeadersSerializerId = -1;
78                 private int responseHeadersSerializerId = -1;
79                 private int faultHeadersSerializerId = -1;
80                 
81                 internal XmlSerializer RequestSerializer
82                 {
83                         get { return TypeStub.GetSerializer (requestSerializerId); }
84                 }
85                 
86                 internal XmlSerializer ResponseSerializer
87                 {
88                         get { return TypeStub.GetSerializer (responseSerializerId); }
89                 }
90                 
91                 internal XmlSerializer RequestHeadersSerializer
92                 {
93                         get { return requestHeadersSerializerId != -1 ? TypeStub.GetSerializer (requestHeadersSerializerId) : null; }
94                 }
95                 
96                 internal XmlSerializer ResponseHeadersSerializer
97                 {
98                         get { return responseHeadersSerializerId != -1 ? TypeStub.GetSerializer (responseHeadersSerializerId) : null; }
99                 }
100                 
101                 internal XmlSerializer FaultHeadersSerializer
102                 {
103                         get { return faultHeadersSerializerId != -1 ? TypeStub.GetSerializer (faultHeadersSerializerId) : null; }
104                 }
105                 
106
107                 //
108                 // Constructor
109                 //
110                 public SoapMethodStubInfo (TypeStubInfo typeStub, LogicalMethodInfo source, object kind, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter)
111                 : base (typeStub, source)
112                 {
113                         SoapTypeStubInfo parent = (SoapTypeStubInfo) typeStub;
114                         XmlElementAttribute optional_ns = null;
115
116                         if (kind == null) {
117                                 Use = parent.Use;
118                                 RequestName = "";
119                                 RequestNamespace = "";
120                                 ResponseName = "";
121                                 ResponseNamespace = "";
122                                 ParameterStyle = parent.ParameterStyle;
123                                 SoapBindingStyle = parent.SoapBindingStyle;
124                                 OneWay = false;
125                         }
126                         else if (kind is SoapDocumentMethodAttribute){
127                                 SoapDocumentMethodAttribute dma = (SoapDocumentMethodAttribute) kind;
128                                 
129                                 Use = dma.Use;
130                                 if (Use == SoapBindingUse.Default) {
131                                         if (parent.SoapBindingStyle == SoapBindingStyle.Document)
132                                                 Use = parent.Use;
133                                         else
134                                                 Use = SoapBindingUse.Literal;
135                                 }
136                                 
137                                 Action = dma.Action;
138                                 Binding = dma.Binding;
139                                 RequestName = dma.RequestElementName;
140                                 RequestNamespace = dma.RequestNamespace;
141                                 ResponseName = dma.ResponseElementName;
142                                 ResponseNamespace = dma.ResponseNamespace;
143                                 ParameterStyle = dma.ParameterStyle;
144                                 if (ParameterStyle == SoapParameterStyle.Default)
145                                         ParameterStyle = parent.ParameterStyle;
146                                 OneWay = dma.OneWay;
147                                 SoapBindingStyle = SoapBindingStyle.Document;
148                         } else {
149                                 SoapRpcMethodAttribute rma = (SoapRpcMethodAttribute) kind;
150                                 Use = SoapBindingUse.Encoded;   // RPC always use encoded
151
152                                 Action = rma.Action;
153                                 Binding = rma.Binding;
154                                 
155                                 // When using RPC, MS.NET seems to ignore RequestElementName and
156                                 // MessageName, and it always uses the method name
157                                 RequestName = source.Name;
158                                 ResponseName = source.Name + "Response";
159 //                              RequestName = rma.RequestElementName;
160 //                              ResponseName = rma.ResponseElementName;
161                                 RequestNamespace = rma.RequestNamespace;
162                                 ResponseNamespace = rma.ResponseNamespace;
163                                 ParameterStyle = SoapParameterStyle.Wrapped;
164                                 OneWay = rma.OneWay;
165                                 SoapBindingStyle = SoapBindingStyle.Rpc;
166
167                                 // For RPC calls, make all arguments be part of the empty namespace
168                                 optional_ns = new XmlElementAttribute ();
169                                 optional_ns.Namespace = "";
170                         }
171
172                         if (OneWay){
173                                 if (source.ReturnType != typeof (void))
174                                         throw new Exception ("OneWay methods should not have a return value.");
175                                 if (source.OutParameters.Length != 0)
176                                         throw new Exception ("OneWay methods should not have out/ref parameters.");
177                         }
178                         
179                         BindingInfo binfo = parent.GetBinding (Binding);
180                         if (binfo == null) throw new InvalidOperationException ("Type '" + parent.Type + "' is missing WebServiceBinding attribute that defines a binding named '" + Binding + "'.");
181                         
182                         string serviceNamespace = binfo.Namespace;
183                                 
184                         if (RequestNamespace == "") RequestNamespace = parent.LogicalType.GetWebServiceNamespace (serviceNamespace, Use);
185                         if (ResponseNamespace == "") ResponseNamespace = parent.LogicalType.GetWebServiceNamespace (serviceNamespace, Use);
186                         if (RequestName == "") RequestName = Name;
187                         if (ResponseName == "") ResponseName = Name + "Response";
188                         if (Action == null || Action == "")
189                                 Action = serviceNamespace.EndsWith("/") ? (serviceNamespace + Name) : (serviceNamespace + "/" + Name);
190                         
191                         bool hasWrappingElem = (ParameterStyle == SoapParameterStyle.Wrapped);
192                         bool writeAccessors = (SoapBindingStyle == SoapBindingStyle.Rpc);
193                         
194                         XmlReflectionMember [] in_members = BuildRequestReflectionMembers (optional_ns);
195                         XmlReflectionMember [] out_members = BuildResponseReflectionMembers (optional_ns);
196
197                         if (Use == SoapBindingUse.Literal) {
198                                 xmlImporter.IncludeTypes (source.CustomAttributeProvider);
199                                 InputMembersMapping = xmlImporter.ImportMembersMapping (RequestName, RequestNamespace, in_members, hasWrappingElem);
200                                 OutputMembersMapping = xmlImporter.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, hasWrappingElem);
201                         }
202                         else {
203                                 soapImporter.IncludeTypes (source.CustomAttributeProvider);
204                                 InputMembersMapping = soapImporter.ImportMembersMapping (RequestName, RequestNamespace, in_members, hasWrappingElem, writeAccessors);
205                                 OutputMembersMapping = soapImporter.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, hasWrappingElem, writeAccessors);
206                         }
207
208                         requestSerializerId = parent.RegisterSerializer (InputMembersMapping);
209                         responseSerializerId = parent.RegisterSerializer (OutputMembersMapping);
210
211                         object[] o = source.GetCustomAttributes (typeof (SoapHeaderAttribute));
212                         ArrayList allHeaderList = new ArrayList (o.Length);
213                         ArrayList inHeaderList = new ArrayList (o.Length);
214                         ArrayList outHeaderList = new ArrayList (o.Length);
215                         ArrayList faultHeaderList = new ArrayList ();
216                         
217                         SoapHeaderDirection unknownHeaderDirections = (SoapHeaderDirection)0;
218                         
219                         for (int i = 0; i < o.Length; i++) {
220                                 SoapHeaderAttribute att = (SoapHeaderAttribute) o[i];
221                                 MemberInfo[] mems = source.DeclaringType.GetMember (att.MemberName);
222                                 if (mems.Length == 0) throw new InvalidOperationException ("Member " + att.MemberName + " not found in class " + source.DeclaringType.FullName + ".");
223                                 
224                                 HeaderInfo header = new HeaderInfo (mems[0], att);
225                                 allHeaderList.Add (header);
226                                 if (!header.IsUnknownHeader) {
227                                         if ((header.Direction & SoapHeaderDirection.In) != 0)
228                                                 inHeaderList.Add (header);
229                                         if ((header.Direction & SoapHeaderDirection.Out) != 0)
230                                                 outHeaderList.Add (header);
231                                         if ((header.Direction & SoapHeaderDirection.Fault) != 0)
232                                                 faultHeaderList.Add (header);
233                                 } else
234                                         unknownHeaderDirections |= header.Direction;
235                         }
236                         
237                         Headers = (HeaderInfo[]) allHeaderList.ToArray (typeof(HeaderInfo));
238
239                         if (inHeaderList.Count > 0 || (unknownHeaderDirections & SoapHeaderDirection.In) != 0) {
240                                 InHeaders = (HeaderInfo[]) inHeaderList.ToArray (typeof(HeaderInfo));
241                                 XmlReflectionMember[] members = BuildHeadersReflectionMembers (InHeaders);
242                                 
243                                 if (Use == SoapBindingUse.Literal)
244                                         InputHeaderMembersMapping = xmlImporter.ImportMembersMapping ("", RequestNamespace, members, false);
245                                 else
246                                         InputHeaderMembersMapping = soapImporter.ImportMembersMapping ("", RequestNamespace, members, false, false);
247                                 
248                                 requestHeadersSerializerId = parent.RegisterSerializer (InputHeaderMembersMapping);
249                         }
250                         
251                         if (outHeaderList.Count > 0 || (unknownHeaderDirections & SoapHeaderDirection.Out) != 0) {
252                                 OutHeaders = (HeaderInfo[]) outHeaderList.ToArray (typeof(HeaderInfo));
253                                 XmlReflectionMember[] members = BuildHeadersReflectionMembers (OutHeaders);
254                                 
255                                 if (Use == SoapBindingUse.Literal)
256                                         OutputHeaderMembersMapping = xmlImporter.ImportMembersMapping ("", RequestNamespace, members, false);
257                                 else
258                                         OutputHeaderMembersMapping = soapImporter.ImportMembersMapping ("", RequestNamespace, members, false, false);
259                                 
260                                 responseHeadersSerializerId = parent.RegisterSerializer (OutputHeaderMembersMapping);
261                         }
262                         
263                         if (faultHeaderList.Count > 0 || (unknownHeaderDirections & SoapHeaderDirection.Fault) != 0) {
264                                 FaultHeaders = (HeaderInfo[]) faultHeaderList.ToArray (typeof(HeaderInfo));
265                                 XmlReflectionMember[] members = BuildHeadersReflectionMembers (FaultHeaders);
266                                 
267                                 if (Use == SoapBindingUse.Literal)
268                                         FaultHeaderMembersMapping = xmlImporter.ImportMembersMapping ("", RequestNamespace, members, false);
269                                 else
270                                         FaultHeaderMembersMapping = soapImporter.ImportMembersMapping ("", RequestNamespace, members, false, false);
271                                 
272                                 faultHeadersSerializerId = parent.RegisterSerializer (FaultHeaderMembersMapping);
273                         }
274                         
275                         SoapExtensions = SoapExtension.GetMethodExtensions (source);
276                 }
277
278                 XmlReflectionMember [] BuildRequestReflectionMembers (XmlElementAttribute optional_ns)
279                 {
280                         ParameterInfo [] input = MethodInfo.InParameters;
281                         XmlReflectionMember [] in_members = new XmlReflectionMember [input.Length];
282
283                         for (int i = 0; i < input.Length; i++)
284                         {
285                                 XmlReflectionMember m = new XmlReflectionMember ();
286                                 m.IsReturnValue = false;
287                                 m.MemberName = input [i].Name;
288                                 m.MemberType = input [i].ParameterType;
289
290                                 m.XmlAttributes = new XmlAttributes (input[i]);
291                                 m.SoapAttributes = new SoapAttributes (input[i]);
292
293                                 if (m.MemberType.IsByRef)
294                                         m.MemberType = m.MemberType.GetElementType ();
295                                 if (optional_ns != null)
296                                         m.XmlAttributes.XmlElements.Add (optional_ns);
297                                 in_members [i] = m;
298                         }
299                         return in_members;
300                 }
301                 
302                 XmlReflectionMember [] BuildResponseReflectionMembers (XmlElementAttribute optional_ns)
303                 {
304                         ParameterInfo [] output = MethodInfo.OutParameters;
305                         bool has_return_value = !(OneWay || MethodInfo.ReturnType == typeof (void));
306                         XmlReflectionMember [] out_members = new XmlReflectionMember [(has_return_value ? 1 : 0) + output.Length];
307                         XmlReflectionMember m;
308                         int idx = 0;
309
310                         if (has_return_value)
311                         {
312                                 m = new XmlReflectionMember ();
313                                 m.IsReturnValue = true;
314                                 m.MemberName = RequestName + "Result";
315                                 m.MemberType = MethodInfo.ReturnType;
316
317                                 m.XmlAttributes = new XmlAttributes (MethodInfo.ReturnTypeCustomAttributeProvider);
318                                 m.SoapAttributes = new SoapAttributes (MethodInfo.ReturnTypeCustomAttributeProvider);
319
320                                 if (optional_ns != null)
321                                         m.XmlAttributes.XmlElements.Add (optional_ns);
322                                 idx++;
323                                 out_members [0] = m;
324                         }
325                         
326                         for (int i = 0; i < output.Length; i++)
327                         {
328                                 m = new XmlReflectionMember ();
329                                 m.IsReturnValue = false;
330                                 m.MemberName = output [i].Name;
331                                 m.MemberType = output [i].ParameterType;
332                                 m.XmlAttributes = new XmlAttributes (output[i]);
333                                 m.SoapAttributes = new SoapAttributes (output[i]);
334
335                                 if (m.MemberType.IsByRef)
336                                         m.MemberType = m.MemberType.GetElementType ();
337                                 if (optional_ns != null)
338                                         m.XmlAttributes.XmlElements.Add (optional_ns);
339                                 out_members [i + idx] = m;
340                         }
341                         return out_members;
342                 }
343
344                 XmlReflectionMember [] BuildHeadersReflectionMembers (HeaderInfo[] headers)
345                 {
346                         XmlReflectionMember [] mems = new XmlReflectionMember [headers.Length];
347
348                         for (int n=0; n<headers.Length; n++)
349                         {
350                                 HeaderInfo header = headers [n];
351                                 
352                                 XmlReflectionMember m = new XmlReflectionMember ();
353                                 m.IsReturnValue = false;
354                                 m.MemberName = header.HeaderType.Name;
355                                 m.MemberType = header.HeaderType;
356
357                                 // MS.NET reflects header classes in a weird way. The root element
358                                 // name is the CLR class name unless it is specified in an XmlRootAttribute.
359                                 // The usual is to use the xml type name by default, but not in this case.
360                                 
361                                 XmlAttributes ats = new XmlAttributes (header.HeaderType);
362                                 if (ats.XmlRoot != null) {
363                                         XmlElementAttribute xe = new XmlElementAttribute ();
364                                         xe.ElementName = ats.XmlRoot.ElementName;
365                                         xe.Namespace = ats.XmlRoot.Namespace;
366                                         m.XmlAttributes = new XmlAttributes ();
367                                         m.XmlAttributes.XmlElements.Add (xe);
368                                 }
369                                 
370                                 mems [n] = m;
371                         }
372                         return mems;
373                 }
374
375                 public HeaderInfo GetHeaderInfo (Type headerType)
376                 {
377                         foreach (HeaderInfo headerInfo in Headers)
378                                 if (headerInfo.HeaderType == headerType) return headerInfo;
379                         return null;
380                 }
381                 
382                 public XmlSerializer GetBodySerializer (SoapHeaderDirection dir)
383                 {
384                         switch (dir) {
385                                 case SoapHeaderDirection.In: return RequestSerializer;
386                                 case SoapHeaderDirection.Out: return ResponseSerializer;
387                                 case SoapHeaderDirection.Fault: return Fault.Serializer;
388                                 default: return null;
389                         }
390                 }
391                 
392                 public XmlSerializer GetHeaderSerializer (SoapHeaderDirection dir)
393                 {
394                         switch (dir) {
395                                 case SoapHeaderDirection.In: return RequestHeadersSerializer;
396                                 case SoapHeaderDirection.Out: return ResponseHeadersSerializer;
397                                 case SoapHeaderDirection.Fault: return FaultHeadersSerializer;
398                                 default: return null;
399                         }
400                 }
401                 
402                 HeaderInfo[] GetHeaders (SoapHeaderDirection dir)
403                 {
404                         switch (dir) {
405                                 case SoapHeaderDirection.In: return InHeaders;
406                                 case SoapHeaderDirection.Out: return OutHeaders;
407                                 case SoapHeaderDirection.Fault: return FaultHeaders;
408                                 default: return null;
409                         }
410                 }
411                 
412                 public object[] GetHeaderValueArray (SoapHeaderDirection dir, SoapHeaderCollection headers)
413                 {
414                         HeaderInfo[] headerInfos = GetHeaders (dir);
415                         if (headerInfos == null) return null;
416
417                         object[] hs = new object [headerInfos.Length];
418                         
419                         for (int n=0; n<headers.Count; n++) {
420                                 SoapHeader h = headers[n];
421                                 Type t = h.GetType();
422                                 for (int i=0; i<headerInfos.Length; i++)
423                                         if (headerInfos [i].HeaderType == t)
424                                                 hs [i] = h;
425                         }
426                         return hs;
427                 }
428         }
429
430         internal class HeaderInfo
431         {
432                 internal MemberInfo Member;
433                 internal SoapHeaderAttribute AttributeInfo;
434                 internal Type HeaderType;
435                 internal bool IsUnknownHeader;
436
437                 public HeaderInfo (MemberInfo member, SoapHeaderAttribute attributeInfo)
438                 {
439                         Member = member;
440                         AttributeInfo = attributeInfo;
441                         if (Member is PropertyInfo) HeaderType = ((PropertyInfo)Member).PropertyType;
442                         else HeaderType = ((FieldInfo)Member).FieldType;
443                         
444                         if (HeaderType == typeof(SoapHeader) || HeaderType == typeof(SoapUnknownHeader) ||
445                                 HeaderType == typeof(SoapHeader[]) || HeaderType == typeof(SoapUnknownHeader[]))
446                         {
447                                 IsUnknownHeader = true;
448                         }
449                         else if (!typeof(SoapHeader).IsAssignableFrom (HeaderType))
450                                 throw new InvalidOperationException (string.Format ("Header members type must be a SoapHeader subclass"));
451                 }
452                 
453                 public object GetHeaderValue (object ob)
454                 {
455                         if (Member is PropertyInfo) return ((PropertyInfo)Member).GetValue (ob, null);
456                         else return ((FieldInfo)Member).GetValue (ob);
457                 }
458
459                 public void SetHeaderValue (object ob, SoapHeader header)
460                 {
461                         object value = header;
462                         if (IsUnknownHeader && HeaderType.IsArray)
463                         {
464                                 SoapUnknownHeader uheader = header as SoapUnknownHeader;
465                                 SoapUnknownHeader[] array = (SoapUnknownHeader[]) GetHeaderValue (ob);
466                                 if (array == null || array.Length == 0) {
467                                         value = new SoapUnknownHeader[] { uheader };
468                                 }
469                                 else {
470                                         SoapUnknownHeader[] newArray = new SoapUnknownHeader [array.Length+1];
471                                         Array.Copy (array, newArray, array.Length);
472                                         newArray [array.Length] = uheader;
473                                         value = newArray;
474                                 }
475                         }
476                         
477                         if (Member is PropertyInfo) ((PropertyInfo)Member).SetValue (ob, value, null);
478                         else ((FieldInfo)Member).SetValue (ob, value);
479                 }
480                 
481                 public SoapHeaderDirection Direction
482                 {
483                         get { return AttributeInfo.Direction; }
484                 }
485         }
486
487
488         //
489         // Holds the metadata loaded from the type stub, as well as
490         // the metadata for all the methods in the type
491         //
492         internal class SoapTypeStubInfo : TypeStubInfo
493         {
494                 Hashtable[] header_serializers = new Hashtable [3];
495                 Hashtable[] header_serializers_byname = new Hashtable [3];
496                 Hashtable methods_byaction = new Hashtable (); 
497
498                 // Precomputed
499                 internal SoapParameterStyle      ParameterStyle;
500                 internal SoapServiceRoutingStyle RoutingStyle;
501                 internal SoapBindingUse          Use;
502                 internal SoapExtensionRuntimeConfig[][] SoapExtensions;
503                 internal SoapBindingStyle SoapBindingStyle;
504                 internal XmlReflectionImporter  xmlImporter;
505                 internal SoapReflectionImporter soapImporter;
506
507                 public SoapTypeStubInfo (LogicalTypeInfo logicalTypeInfo)
508                 : base (logicalTypeInfo)
509                 {
510                         xmlImporter = new XmlReflectionImporter ();
511                         soapImporter = new SoapReflectionImporter ();
512                         
513                         object [] o;
514
515                         o = Type.GetCustomAttributes (typeof (WebServiceBindingAttribute), false);
516                         
517                         if (typeof (SoapHttpClientProtocol).IsAssignableFrom (Type))
518                         {
519                                 if (o.Length == 0)
520                                         throw new InvalidOperationException ("WebServiceBindingAttribute is required on proxy class '" + Type + "'.");
521                                 if (o.Length > 1)
522                                         throw new InvalidOperationException ("Only one WebServiceBinding attribute may be specified on type '" + Type + "'.");
523                                         
524                                 // Remove the default binding, it is not needed since there is always
525                                 // a binding attribute.
526                                 Bindings.Clear ();
527                         }
528                                 
529                         foreach (WebServiceBindingAttribute at in o)
530                                 AddBinding (new BindingInfo (at, LogicalType.WebServiceNamespace));
531
532                         o = Type.GetCustomAttributes (typeof (SoapDocumentServiceAttribute), false);
533                         if (o.Length == 1){
534                                 SoapDocumentServiceAttribute a = (SoapDocumentServiceAttribute) o [0];
535
536                                 ParameterStyle = a.ParameterStyle;
537                                 RoutingStyle = a.RoutingStyle;
538                                 Use = a.Use;
539                                 SoapBindingStyle = SoapBindingStyle.Document;
540                         } else {
541                                 o = Type.GetCustomAttributes (typeof (SoapRpcServiceAttribute), false);
542                                 if (o.Length == 1){
543                                         SoapRpcServiceAttribute srs = (SoapRpcServiceAttribute) o [0];
544                                         
545                                         ParameterStyle = SoapParameterStyle.Wrapped;
546                                         RoutingStyle = srs.RoutingStyle;
547                                         Use = SoapBindingUse.Encoded;
548                                         SoapBindingStyle = SoapBindingStyle.Rpc;
549                                 } else {
550                                         ParameterStyle = SoapParameterStyle.Wrapped;
551                                         RoutingStyle = SoapServiceRoutingStyle.SoapAction;
552                                         Use = SoapBindingUse.Literal;
553                                         SoapBindingStyle = SoapBindingStyle.Document;
554                                 }
555                         }
556                         
557                         if (ParameterStyle == SoapParameterStyle.Default) ParameterStyle = SoapParameterStyle.Wrapped;
558                         if (Use == SoapBindingUse.Default) Use = SoapBindingUse.Literal;
559                         
560                         xmlImporter.IncludeTypes (Type);
561                         soapImporter.IncludeTypes (Type);
562
563                         SoapExtensions = SoapExtension.GetTypeExtensions (Type);
564                 }
565
566                 public override XmlReflectionImporter XmlImporter 
567                 {
568                         get { return xmlImporter; }
569                 }
570
571                 public override SoapReflectionImporter SoapImporter 
572                 {
573                         get { return soapImporter; }
574                 }
575                 
576                 public override string ProtocolName
577                 {
578                         get { return "Soap"; }
579                 }
580                 
581                 protected override MethodStubInfo CreateMethodStubInfo (TypeStubInfo parent, LogicalMethodInfo lmi, bool isClientProxy)
582                 {
583                         SoapMethodStubInfo res = null;
584                         object [] ats = lmi.GetCustomAttributes (typeof (SoapDocumentMethodAttribute));
585                         if (ats.Length == 0) ats = lmi.GetCustomAttributes (typeof (SoapRpcMethodAttribute));
586
587                         if (ats.Length == 0 && isClientProxy)
588                                 return null;
589                         else if (ats.Length == 0)
590                                 res = new SoapMethodStubInfo (parent, lmi, null, xmlImporter, soapImporter);
591                         else
592                                 res = new SoapMethodStubInfo (parent, lmi, ats[0], xmlImporter, soapImporter);
593                                 
594                         methods_byaction [res.Action] = res;
595                         return res;
596                 }
597                 
598                 public SoapMethodStubInfo GetMethodForSoapAction (string name)
599                 {
600                         return (SoapMethodStubInfo) methods_byaction [name.Trim ('"',' ')];
601                 }
602         }
603 }