File: WebMethodAttribute.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (349 lines) | stat: -rw-r--r-- 15,986 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
//------------------------------------------------------------------------------
// <copyright file="WebMethodAttribute.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------

namespace System.Web.Services {

    using System;
    using System.Reflection;
    using System.Collections;
    using System.Web.Util;
    using System.Web.Services.Protocols;
    using System.Xml.Serialization;
    using System.EnterpriseServices;
    using System.Text;
    using System.Runtime.InteropServices;

    /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute"]/*' />
    /// <devdoc>
    ///    <para> The WebMethod attribute must be placed on a method in a Web Service class to mark it as available
    ///       to be called via the Web. The method and class must be marked public and must run inside of
    ///       an ASP.NET Web application.</para>
    /// </devdoc>
    [AttributeUsage(AttributeTargets.Method)]
    public sealed class WebMethodAttribute : Attribute {
        private int transactionOption; // this is an int to prevent system.enterpriseservices.dll from getting loaded
        private bool enableSession;
        private int cacheDuration;
        private bool bufferResponse;
        private string description;
        private string messageName;
        
        private bool transactionOptionSpecified;
        private bool enableSessionSpecified;
        private bool cacheDurationSpecified;
        private bool bufferResponseSpecified;
        private bool descriptionSpecified;
        private bool messageNameSpecified;

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.WebMethodAttribute"]/*' />
        /// <devdoc>
        /// <para>Initializes a new instance of the <see cref='System.Web.Services.WebMethodAttribute'/> 
        /// class.</para>
        /// </devdoc>
        public WebMethodAttribute() {
            enableSession = false;
            transactionOption = 0; // TransactionOption.Disabled
            cacheDuration = 0;
            bufferResponse = true;
        }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.WebMethodAttribute1"]/*' />
        /// <devdoc>
        /// <para>Initializes a new instance of the <see cref='System.Web.Services.WebMethodAttribute'/> 
        /// class.</para>
        /// </devdoc>
        public WebMethodAttribute(bool enableSession) 
            : this() {
            EnableSession = enableSession;
        }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.WebMethodAttribute2"]/*' />
        /// <devdoc>
        /// <para>Initializes a new instance of the <see cref='System.Web.Services.WebMethodAttribute'/> 
        /// class.</para>
        /// </devdoc>
        public WebMethodAttribute(bool enableSession, TransactionOption transactionOption) 
            : this() {
            EnableSession = enableSession;
            this.transactionOption = (int)transactionOption;
            transactionOptionSpecified = true;
        }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.WebMethodAttribute3"]/*' />
        /// <devdoc>
        /// <para>Initializes a new instance of the <see cref='System.Web.Services.WebMethodAttribute'/> 
        /// class.</para>
        /// </devdoc>
        public WebMethodAttribute(bool enableSession, TransactionOption transactionOption, int cacheDuration) {
            EnableSession = enableSession;
            this.transactionOption = (int)transactionOption;
            transactionOptionSpecified = true;
            CacheDuration = cacheDuration;
            BufferResponse = true;
        }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.WebMethodAttribute4"]/*' />
        /// <devdoc>
        /// <para>Initializes a new instance of the <see cref='System.Web.Services.WebMethodAttribute'/> 
        /// class.</para>
        /// </devdoc>
        public WebMethodAttribute(bool enableSession, TransactionOption transactionOption, int cacheDuration, bool bufferResponse) {
            EnableSession = enableSession;
            this.transactionOption = (int)transactionOption;
            transactionOptionSpecified = true;
            CacheDuration = cacheDuration;
            BufferResponse = bufferResponse;
        }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.Description"]/*' />
        /// <devdoc>
        ///    <para> A message that describes the Web service method. 
        ///       The message is used in description files generated for a Web Service, such as the Service Contract and the Service Description page.</para>
        /// </devdoc>
        public string Description {
            get {
                return (description == null) ? string.Empty : description;
            }

            set {
                description = value;
                descriptionSpecified = true;
            }
        }
        internal bool DescriptionSpecified { get { return descriptionSpecified; } }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.EnableSession"]/*' />
        /// <devdoc>
        ///    <para>Indicates wheter session state is enabled for a Web service Method. The default is false.</para>
        /// </devdoc>
        public bool EnableSession {
            get {
                return enableSession;
            }

            set {
                enableSession = value;
                enableSessionSpecified = true;
            }
        }
        internal bool EnableSessionSpecified { get { return enableSessionSpecified; } }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.CacheDuration"]/*' />
        /// <devdoc>
        ///    <para>Indicates the number of seconds the response should be cached. Defaults to 0 (no caching).
        ///          Should be used with caution when requests are likely to be very large.</para>
        /// </devdoc>
        public int CacheDuration {
            get {
                return cacheDuration;
            }

            set {
                cacheDuration = value;
                cacheDurationSpecified = true;
            }
        }
        internal bool CacheDurationSpecified { get { return cacheDurationSpecified; } }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.BufferResponse"]/*' />
        /// <devdoc>
        ///    <para>Indicates whether the response for this request should be buffered. Defaults to false.</para>
        /// </devdoc>
        public bool BufferResponse {
            get {
                return bufferResponse;
            }

            set {
                bufferResponse = value;
                bufferResponseSpecified = true;
            }
        }
        internal bool BufferResponseSpecified { get { return bufferResponseSpecified; } }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.TransactionOption"]/*' />
        /// <devdoc>
        ///    <para> 
        ///       Indicates the transaction participation mode of a Web Service Method. </para>
        /// </devdoc>
        public TransactionOption TransactionOption {            
            get {
                return (TransactionOption)transactionOption;
            }    
            set {
                transactionOption = (int)value;
                transactionOptionSpecified = true;
            }                                        
        }
        internal bool TransactionOptionSpecified { get { return transactionOptionSpecified; } }

        internal bool TransactionEnabled {
            get {
                return transactionOption != 0;
            }
        }

        /// <include file='doc\WebMethodAttribute.uex' path='docs/doc[@for="WebMethodAttribute.MessageName"]/*' />
        /// <devdoc>
        ///    <para>The name used for the request and response message containing the 
        ///    data passed to and returned from this method.</para>
        /// </devdoc>
        public string MessageName {
            get {
                return messageName == null ? string.Empty : messageName;
            }

            set {
                messageName = value;
                messageNameSpecified = true;
            }
        }
        internal bool MessageNameSpecified { get { return messageNameSpecified; } }
    }

    internal class WebMethodReflector {
        private WebMethodReflector() { }
        /*
        internal static WebMethodAttribute GetAttribute(MethodInfo implementation) {
            return GetAttribute(implementation, null);
        }
        */

        internal static WebMethodAttribute GetAttribute(MethodInfo implementation, MethodInfo declaration) {
            WebMethodAttribute declAttribute = null;
            WebMethodAttribute implAttribute = null;
            object[] attrs;

            if (declaration != null) {
                attrs = declaration.GetCustomAttributes(typeof(WebMethodAttribute), false);
                if (attrs.Length > 0) {
                    declAttribute = (WebMethodAttribute)attrs[0];
                }
            }
            attrs = implementation.GetCustomAttributes(typeof(WebMethodAttribute), false);
            if (attrs.Length > 0) {
                implAttribute = (WebMethodAttribute)attrs[0];
            }
            if (declAttribute == null) {
                return implAttribute;
            }
            if (implAttribute == null) {
                return declAttribute;
            }
            if (implAttribute.MessageNameSpecified) {
                throw new InvalidOperationException(Res.GetString(Res.ContractOverride, implementation.Name, implementation.DeclaringType.FullName, declaration.DeclaringType.FullName, declaration.ToString(), "WebMethod.MessageName"));
            }
            // merge two attributes
            WebMethodAttribute attribute = new WebMethodAttribute(implAttribute.EnableSessionSpecified ? implAttribute.EnableSession : declAttribute.EnableSession);
            attribute.TransactionOption = implAttribute.TransactionOptionSpecified ? implAttribute.TransactionOption : declAttribute.TransactionOption;
            attribute.CacheDuration = implAttribute.CacheDurationSpecified ? implAttribute.CacheDuration : declAttribute.CacheDuration;
            attribute.BufferResponse = implAttribute.BufferResponseSpecified ? implAttribute.BufferResponse : declAttribute.BufferResponse;
            attribute.Description = implAttribute.DescriptionSpecified ? implAttribute.Description : declAttribute.Description;
            return attribute;
        }

        // Find the MethodInfo of the interface method from the implemented method
        internal static MethodInfo FindInterfaceMethodInfo(Type type, string signature)
        {
            Type[] interfaces = type.GetInterfaces();
            // Foreach type get the interface map and then search each TargetMethod
            // till we find the right one. Once found return the corresponding interface method 
            foreach (Type i in interfaces) {
                InterfaceMapping map = type.GetInterfaceMap(i);
                MethodInfo[] targetMethods = map.TargetMethods;
                for (int j = 0; j < targetMethods.Length; j++) {
                    if (targetMethods[j].ToString() == signature) {
                        return map.InterfaceMethods[j];
                    }
                }
            }
            return null;
        }

        internal static LogicalMethodInfo[] GetMethods(Type type) {
            if (type.IsInterface) {
                throw new InvalidOperationException(Res.GetString(Res.NeedConcreteType, type.FullName));
            }
            ArrayList list = new ArrayList();
            MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
            Hashtable unique = new Hashtable();
            Hashtable methodInfos = new Hashtable();
            for (int i = 0; i < methods.Length; i++) {
                Type declaringType = methods[i].DeclaringType;
                if (declaringType == typeof(object))
                    continue;
                if (declaringType == typeof(WebService))
                    continue;
                string signature = methods[i].ToString();
                MethodInfo declaration = FindInterfaceMethodInfo(declaringType, signature);
                WebServiceBindingAttribute binding = null;
                
                if (declaration != null) {
                    object[] attrs = declaration.DeclaringType.GetCustomAttributes(typeof(WebServiceBindingAttribute), false);
                    if (attrs.Length > 0) {
                        if (attrs.Length > 1)
                            throw new ArgumentException(Res.GetString(Res.OnlyOneWebServiceBindingAttributeMayBeSpecified1, declaration.DeclaringType.FullName), "type");
                        binding = (WebServiceBindingAttribute)attrs[0];
                        if (binding.Name == null || binding.Name.Length == 0) {
                            binding.Name = declaration.DeclaringType.Name;
                        }
                    }
                    else {
                        declaration = null;
                    }
                }
                else if (!methods[i].IsPublic) {
                    continue;
                }
                WebMethodAttribute attribute = WebMethodReflector.GetAttribute(methods[i], declaration);
                if (attribute == null)
                    continue;

                WebMethod webMethod = new WebMethod(declaration, binding, attribute);
                methodInfos.Add(methods[i], webMethod);
                MethodInfo method = (MethodInfo)unique[signature];
                if (method == null) {
                    unique.Add(signature, methods[i]);
                    list.Add(methods[i]);
                }
                else {
                    if (method.DeclaringType.IsAssignableFrom(methods[i].DeclaringType)) {
                        unique[signature] = methods[i];
                        list[list.IndexOf(method)] = methods[i];
                    }
                }
            }
            return LogicalMethodInfo.Create((MethodInfo[])list.ToArray(typeof(MethodInfo)), LogicalMethodTypes.Async | LogicalMethodTypes.Sync, methodInfos);
        }

        internal static void IncludeTypes(LogicalMethodInfo[] methods, XmlReflectionImporter importer) {
            for (int i = 0; i < methods.Length; i++) {
                LogicalMethodInfo method = methods[i];
                IncludeTypes(method, importer);
            }
        }

        internal static void IncludeTypes(LogicalMethodInfo method, XmlReflectionImporter importer) {
            if (method.Declaration != null) {
                importer.IncludeTypes(method.Declaration.DeclaringType);
                importer.IncludeTypes(method.Declaration);
            }
            importer.IncludeTypes(method.DeclaringType);
            importer.IncludeTypes(method.CustomAttributeProvider);
        }
    }

    internal class WebMethod {
        internal MethodInfo declaration;
        internal WebServiceBindingAttribute binding;
        internal WebMethodAttribute attribute;
        internal WebMethod(MethodInfo declaration, WebServiceBindingAttribute binding, WebMethodAttribute attribute) {
            this.declaration = declaration;
            this.binding = binding;
            this.attribute = attribute;
        }
    }
}