Пример #1
0
        /// <summary>
        /// Caches a web method definition
        /// </summary>
        /// <param name="wsType"></param>
        /// <param name="methods"></param>
        /// <param name="method"></param>
        private void AddMethod(Type wsType, Dictionary <string, WebMethodDef> methods, MethodInfo method)
        {
            object[] wmAttribs = method.GetCustomAttributes(typeof(WebMethodAttribute), false);

            if (wmAttribs.Length == 0)
            {
                return;
            }

            ScriptMethodAttribute sm = null;

            object[] responseAttribs = method.GetCustomAttributes(typeof(ScriptMethodAttribute), false);
            if (responseAttribs.Length > 0)
            {
                sm = (ScriptMethodAttribute)responseAttribs[0];
            }


            TransactionalMethodAttribute tm = null;

            object[] tmAttribs = method.GetCustomAttributes(typeof(TransactionalMethodAttribute), false);
            if (tmAttribs.Length > 0)
            {
                tm = (TransactionalMethodAttribute)tmAttribs[0];
            }

            WebMethodDef wmd = new WebMethodDef(this, method, (WebMethodAttribute)wmAttribs[0], sm, tm);

            methods[wmd.MethodName] = wmd;
        }
Пример #2
0
 public void Dispose()
 {
     this.MethodName = null;
     this.Target = null;
     this.ServiceDef = null;
     this.MethodDef = null;
     this.Context = null;
     this.ExtraData = null;
 }
Пример #3
0
 public void Dispose()
 {
     this.MethodName = null;
     this.Target     = null;
     this.ServiceDef = null;
     this.MethodDef  = null;
     this.Context    = null;
     this.ExtraData  = null;
 }
Пример #4
0
 public void Dispose()
 {
     MethodName = null;
     Target     = null;
     ServiceDef = null;
     MethodDef  = null;
     Context    = null;
     ExtraData  = null;
 }
Пример #5
0
 internal AsyncWebMethodState(string methodName, IDisposable target, WebServiceDef wsDef, WebMethodDef wmDef, HttpContext context, object extraData)
 {
     MethodName = methodName;
     Target     = target;
     ServiceDef = wsDef;
     MethodDef  = wmDef;
     Context    = context;
     ExtraData  = extraData;
 }
Пример #6
0
        public WebMethodDef(WebServiceDef wsDef, MethodInfo method, WebMethodAttribute wmAttribute, ScriptMethodAttribute smAttribute, TransactionalMethodAttribute tmAttribute, ETagMethodAttribute emAttribute)
        {
            this.MethodType      = method;
            this.WebMethodAtt    = wmAttribute;
            this.ScriptMethodAtt = smAttribute;
            this.TransactionAtt  = tmAttribute;

            if (null != emAttribute)
            {
                this.IsETagEnabled = emAttribute.Enabled;
            }

            if (wmAttribute != null && !string.IsNullOrEmpty(wmAttribute.MessageName))
            {
                this.MethodName = wmAttribute.MessageName;
            }
            else
            {
                this.MethodName = method.Name;
            }

            // HTTP GET method is allowed only when there's a [ScriptMethod] attribute and UseHttpGet is true
            this.IsGetAllowed = (this.ScriptMethodAtt != null && this.ScriptMethodAtt.UseHttpGet);

            this.ResponseFormat = (this.ScriptMethodAtt != null ? this.ScriptMethodAtt.ResponseFormat : ResponseFormat.Json);

            MethodInfo beginMethod = wsDef.WSType.GetMethod("Begin" + method.Name, BINDING_FLAGS);

            if (null != beginMethod)
            {
                // The BeginXXX method must have the [ScriptMethod] attribute
                object[] scriptMethodAttributes = beginMethod.GetCustomAttributes(typeof(ScriptMethodAttribute), false);
                if (scriptMethodAttributes.Length > 0)
                {
                    // Asynchronous methods found for the function
                    this.HasAsyncMethods = true;

                    this.BeginMethod = new WebMethodDef(wsDef, beginMethod, null, null, null, null);

                    MethodInfo endMethod = wsDef.WSType.GetMethod("End" + method.Name, BINDING_FLAGS);
                    this.EndMethod = new WebMethodDef(wsDef, endMethod, null, null, null, null);

                    // get all parameters of begin web method and then leave last two parameters in the input parameters list because
                    // last two parameters are for AsyncCallback and Async State
                    ParameterInfo[] allParameters   = beginMethod.GetParameters();
                    ParameterInfo[] inputParameters = new ParameterInfo[allParameters.Length - 2];
                    Array.Copy(allParameters, inputParameters, allParameters.Length - 2);

                    this.BeginMethod.InputParameters         = new List <ParameterInfo>(inputParameters);
                    this.BeginMethod.InputParametersWithAsyc = new List <ParameterInfo>(allParameters);
                }
            }

            this.InputParameters = new List <ParameterInfo>(method.GetParameters());
        }
Пример #7
0
 internal AsyncWebMethodState(string methodName,
     IDisposable target, WebServiceDef wsDef, WebMethodDef wmDef, HttpContext context,
     object extraData)
 {
     this.MethodName = methodName;
     this.Target = target;
     this.ServiceDef = wsDef;
     this.MethodDef = wmDef;
     this.Context = context;
     this.ExtraData = extraData;
 }
Пример #8
0
        /// <summary>
        /// Execute web method synchronously
        /// </summary>
        /// <param name="context"></param>
        /// <param name="methodDef"></param>
        /// <param name="serviceDef"></param>
        private void ExecuteMethod(HttpContext context, WebMethodDef methodDef, WebServiceDef serviceDef)
        {
            IDictionary <string, object> inputValues = GetRawParams(context, methodDef.InputParameters, serviceDef.Serializer);

            object[] parameters = StrongTypeParameters(inputValues, methodDef.InputParameters);

            object returnValue = null;

            using (IDisposable target = Activator.CreateInstance(serviceDef.WSType) as IDisposable)
            {
                TransactionScope ts = null;
                try
                {
                    // If the method has a transaction attribute, then call the method within a transaction scope
                    if (methodDef.TransactionAtt != null)
                    {
                        TransactionOptions options = new TransactionOptions();
                        options.IsolationLevel = methodDef.TransactionAtt.IsolationLevel;
                        options.Timeout        = TimeSpan.FromSeconds(methodDef.TransactionAtt.Timeout);

                        ts = new TransactionScope(methodDef.TransactionAtt.TransactionOption, options);
                    }

                    returnValue = methodDef.MethodType.Invoke(target, parameters);

                    // If transaction was used, then complete the transaction because no exception was
                    // generated
                    if (null != ts)
                    {
                        ts.Complete();
                    }

                    GenerateResponse(returnValue, context, methodDef, serviceDef);
                }
                catch (Exception x)
                {
                    WebServiceHelper.WriteExceptionJsonString(context, x, serviceDef.Serializer);
                }
                finally
                {
                    // If transaction was started for the method, dispose the transaction. This will
                    // rollback if not committed
                    if (null != ts)
                    {
                        ts.Dispose();
                    }

                    // Dispose the web service
                    target.Dispose();
                }
            }
        }
Пример #9
0
        IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            // Proper Content-Type header must be present in order to make a REST call
            if (!IsRestMethodCall(context.Request))
            {
                return(GenerateErrorResponse(context, "Not a valid REST call", extraData));
            }

            string methodName = context.Request.PathInfo.Substring(1);

            WebServiceDef wsDef     = WebServiceHelper.GetWebServiceType(context, context.Request.FilePath);
            WebMethodDef  methodDef = wsDef.Methods[methodName];

            if (null == methodDef)
            {
                return(GenerateErrorResponse(context, "Web method not supported: " + methodName, extraData));
            }

            // GET request will only be allowed if the method says so
            if (context.Request.HttpMethod == "GET" && !methodDef.IsGetAllowed)
            {
                return(GenerateErrorResponse(context, "Http Get method not supported", extraData));
            }

            context.Response.Filter = new ResponseFilter(context.Response);

            // If the method does not have a BeginXXX and EndXXX pair, execute it synchronously
            if (!methodDef.HasAsyncMethods)
            {
                // Do synchronous call
                ExecuteMethod(context, methodDef, wsDef);

                // Return a result that says method was executed synchronously
                return(new AsmxHandlerSyncResult(extraData));
            }
            else
            {
                // Call the Begin method of web service
                IDisposable target = Activator.CreateInstance(wsDef.WSType) as IDisposable;

                WebMethodDef beginMethod       = methodDef.BeginMethod;
                int          allParameterCount = beginMethod.InputParametersWithAsyc.Count;

                IDictionary <string, object> inputValues = GetRawParams(context, beginMethod.InputParameters, wsDef.Serializer);
                object[] parameterValues = StrongTypeParameters(inputValues, beginMethod.InputParameters);

                // Prepare the list of parameter values which will also include the AsyncCallback and the state
                object[] parameterValuesWithAsync = new object[allParameterCount];
                Array.Copy(parameterValues, parameterValuesWithAsync, parameterValues.Length);

                // Populate last two parameters with async callback and state
                parameterValuesWithAsync[allParameterCount - 2] = cb;

                AsyncWebMethodState webMethodState = new AsyncWebMethodState(methodName, target,
                                                                             wsDef, methodDef, context, extraData);
                parameterValuesWithAsync[allParameterCount - 1] = webMethodState;

                try
                {
                    // Invoke the BeginXXX method and ensure the return result has AsyncWebMethodState. This state
                    // contains context and other information which we need in oreder to call the EndXXX
                    IAsyncResult result = beginMethod.MethodType.Invoke(target, parameterValuesWithAsync) as IAsyncResult;

                    // If execution has completed synchronously within the BeginXXX function, then generate response
                    // immediately. There's no need to call EndXXX
                    if (result.CompletedSynchronously)
                    {
                        object returnValue = result.AsyncState;
                        GenerateResponse(returnValue, context, methodDef, wsDef);

                        target.Dispose();
                        return(new AsmxHandlerSyncResult(extraData));
                    }
                    else
                    {
                        if (result.AsyncState is AsyncWebMethodState)
                        {
                            return(result);
                        }
                        else
                        {
                            throw new InvalidAsynchronousStateException("The state passed in the " + beginMethod.MethodName + " must inherit from " + typeof(AsyncWebMethodState).FullName);
                        }
                    }
                }
                catch (Exception x)
                {
                    target.Dispose();
                    WebServiceHelper.WriteExceptionJsonString(context, x, wsDef.Serializer);
                    return(new AsmxHandlerSyncResult(extraData));
                }
            }
        }
Пример #10
0
        private void GenerateResponse(object returnValue, HttpContext context, WebMethodDef methodDef, WebServiceDef serviceDef)
        {
            if (context.Response.Filter.Length > 0)
            {
                // Response has already been transmitted by the WebMethod.
                // So, do nothing
                return;
            }
            string responseString = null;
            string contentType    = "application/json";

            if (methodDef.ResponseFormat == System.Web.Script.Services.ResponseFormat.Json)
            {
                responseString = "{ d : (" + serviceDef.Serializer.Serialize(returnValue) + ")}";
                contentType    = "application/json";
            }
            else if (methodDef.ResponseFormat == System.Web.Script.Services.ResponseFormat.Xml)
            {
                responseString = returnValue as string;
                contentType    = "text/xml";
            }

            context.Response.ContentType = contentType;

            // If we have response and no redirection happening and client still connected, send response
            if (responseString != null &&
                !context.Response.IsRequestBeingRedirected &&
                context.Response.IsClientConnected)
            {
                // Produce proper cache. If no cache information specified on method and there's been no cache related
                // changes done within the web method code, then default cache will be private, no cache.
                if (IsCacheSet(context.Response) || methodDef.IsETagEnabled)
                {
                    // Cache has been modified within the code. So, do not change any cache policy
                }
                else
                {
                    // Cache is still private. Check if there's any CacheDuration set in WebMethod
                    int cacheDuration = methodDef.WebMethodAtt.CacheDuration;
                    if (cacheDuration > 0)
                    {
                        // If CacheDuration attribute is set, use server side caching
                        context.Response.Cache.SetCacheability(HttpCacheability.Server);
                        context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(cacheDuration));
                        context.Response.Cache.SetSlidingExpiration(false);
                        context.Response.Cache.SetValidUntilExpires(true);

                        if (methodDef.InputParameters.Count > 0)
                        {
                            context.Response.Cache.VaryByParams["*"] = true;
                        }
                        else
                        {
                            context.Response.Cache.VaryByParams.IgnoreParams = true;
                        }
                    }
                    else
                    {
                        context.Response.Cache.SetNoServerCaching();
                        context.Response.Cache.SetMaxAge(TimeSpan.Zero);
                    }
                }

                // Check if there's any need to do ETag match. If ETag matches, produce HTTP 304, otherwise
                // render the content along with the ETag
                if (methodDef.IsETagEnabled)
                {
                    string etag = context.Request.Headers["If-None-Match"];
                    string hash = GetMd5Hash(responseString);

                    if (!string.IsNullOrEmpty(etag))
                    {
                        if (string.Compare(hash, etag, true) == 0)
                        {
                            // Send no body as response and we will just abort it
                            context.Response.ClearContent();
                            context.Response.AppendHeader("Content-Length", "0");
                            context.Response.SuppressContent = true;
                            context.Response.StatusCode      = 304;

                            // No need to produce output response body
                            return;
                        }
                    }

                    // ETag comparison did not happen or comparison did not match. So, we need to produce new ETag
                    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);
                    HttpContext.Current.Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
                    HttpContext.Current.Response.Cache.SetETag(hash);
                    HttpContext.Current.Response.Cache.SetLastModified(DateTime.Now);

                    int cacheDuration = methodDef.WebMethodAtt.CacheDuration;
                    if (cacheDuration > 0)
                    {
                        context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(cacheDuration));
                        context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(cacheDuration));
                    }
                    else
                    {
                        context.Response.Cache.SetMaxAge(TimeSpan.FromSeconds(10));
                    }
                }

                // Convert the response to response encoding, e.g. utf8
                byte[] unicodeBytes = Encoding.Unicode.GetBytes(responseString);
                byte[] utf8Bytes    = Encoding.Convert(Encoding.Unicode, context.Response.ContentEncoding, unicodeBytes);

                // Emit content length in UTF8 encoding string
                context.Response.AppendHeader("Content-Length", utf8Bytes.Length.ToString());

                // Instead of Response.Write which will convert the output to UTF8, use the internal stream
                // to directly write the utf8 bytes
                context.Response.OutputStream.Write(utf8Bytes, 0, utf8Bytes.Length);
            }
            else
            {
                // Send no body as response and we will just abort it
                context.Response.AppendHeader("Content-Length", "0");
                context.Response.ClearContent();
                context.Response.StatusCode = 204; // No Content
            }
        }
Пример #11
0
        private void GenerateResponse(object returnValue, HttpContext context, WebMethodDef methodDef, WebServiceDef serviceDef)
        {
            if (context.Response.Filter.Length > 0)
            {
                // Response has already been transmitted by the WebMethod.
                // So, do nothing
                return;
            }
            string responseString = null;
            string contentType = "application/json";

            if (methodDef.ResponseFormat == System.Web.Script.Services.ResponseFormat.Json)
            {
                responseString = "{ d : (" + serviceDef.Serializer.Serialize(returnValue) + ")}";
                contentType = "application/json";
            }
            else if (methodDef.ResponseFormat == System.Web.Script.Services.ResponseFormat.Xml)
            {
                responseString = returnValue as string;
                contentType = "text/xml";
            }

            context.Response.ContentType = contentType;

            // If we have response and no redirection happening and client still connected, send response
            if (responseString != null
                && !context.Response.IsRequestBeingRedirected
                && context.Response.IsClientConnected)
            {
                // Produce proper cache. If no cache information specified on method and there's been no cache related
                // changes done within the web method code, then default cache will be private, no cache.
                if (IsCacheSet(context.Response) || methodDef.IsETagEnabled)
                {
                    // Cache has been modified within the code. So, do not change any cache policy
                }
                else
                {
                    // Cache is still private. Check if there's any CacheDuration set in WebMethod
                    int cacheDuration = methodDef.WebMethodAtt.CacheDuration;
                    if (cacheDuration > 0)
                    {
                        // If CacheDuration attribute is set, use server side caching
                        context.Response.Cache.SetCacheability(HttpCacheability.Server);
                        context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(cacheDuration));
                        context.Response.Cache.SetSlidingExpiration(false);
                        context.Response.Cache.SetValidUntilExpires(true);

                        if (methodDef.InputParameters.Count > 0)
                        {
                            context.Response.Cache.VaryByParams["*"] = true;
                        }
                        else
                        {
                            context.Response.Cache.VaryByParams.IgnoreParams = true;
                        }
                    }
                    else
                    {
                        context.Response.Cache.SetNoServerCaching();
                        context.Response.Cache.SetMaxAge(TimeSpan.Zero);
                    }
                }

                // Check if there's any need to do ETag match. If ETag matches, produce HTTP 304, otherwise
                // render the content along with the ETag
                if (methodDef.IsETagEnabled)
                {
                    string etag = context.Request.Headers["If-None-Match"];
                    string hash = GetMd5Hash(responseString);

                    if (!string.IsNullOrEmpty(etag))
                    {
                        if (string.Compare(hash, etag, true) == 0)
                        {
                            // Send no body as response and we will just abort it
                            context.Response.ClearContent();
                            context.Response.AppendHeader("Content-Length", "0");
                            context.Response.SuppressContent = true;
                            context.Response.StatusCode = 304;

                            // No need to produce output response body
                            return;
                        }
                    }

                    // ETag comparison did not happen or comparison did not match. So, we need to produce new ETag
                    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);
                    HttpContext.Current.Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
                    HttpContext.Current.Response.Cache.SetETag(hash);
                    HttpContext.Current.Response.Cache.SetLastModified(DateTime.Now);

                    int cacheDuration = methodDef.WebMethodAtt.CacheDuration;
                    if (cacheDuration > 0)
                    {
                        context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(cacheDuration));
                        context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(cacheDuration));
                    }
                    else
                    {
                        context.Response.Cache.SetMaxAge(TimeSpan.FromSeconds(10));
                    }

                }

                // Convert the response to response encoding, e.g. utf8
                byte[] unicodeBytes = Encoding.Unicode.GetBytes(responseString);
                byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, context.Response.ContentEncoding, unicodeBytes);

                // Emit content length in UTF8 encoding string
                context.Response.AppendHeader("Content-Length", utf8Bytes.Length.ToString());

                // Instead of Response.Write which will convert the output to UTF8, use the internal stream
                // to directly write the utf8 bytes
                context.Response.OutputStream.Write(utf8Bytes, 0, utf8Bytes.Length);
            }
            else
            {
                // Send no body as response and we will just abort it
                context.Response.AppendHeader("Content-Length", "0");
                context.Response.ClearContent();
                context.Response.StatusCode = 204; // No Content
            }
        }
Пример #12
0
        /// <summary>
        /// Execute web method synchronously
        /// </summary>
        /// <param name="context"></param>
        /// <param name="methodDef"></param>
        /// <param name="serviceDef"></param>
        private void ExecuteMethod(HttpContext context, WebMethodDef methodDef, WebServiceDef serviceDef)
        {
            IDictionary<string, object> inputValues = GetRawParams(context, methodDef.InputParameters, serviceDef.Serializer);
            object[] parameters = StrongTypeParameters(inputValues, methodDef.InputParameters);

            object returnValue = null;
            using (IDisposable target = Activator.CreateInstance(serviceDef.WSType) as IDisposable)
            {
                TransactionScope ts = null;
                try
                {
                    // If the method has a transaction attribute, then call the method within a transaction scope
                    if (methodDef.TransactionAtt != null)
                    {
                        TransactionOptions options = new TransactionOptions();
                        options.IsolationLevel = methodDef.TransactionAtt.IsolationLevel;
                        options.Timeout = TimeSpan.FromSeconds( methodDef.TransactionAtt.Timeout );

                        ts = new TransactionScope(methodDef.TransactionAtt.TransactionOption, options);
                    }

                    returnValue = methodDef.MethodType.Invoke(target, parameters);

                    // If transaction was used, then complete the transaction because no exception was
                    // generated
                    if( null != ts ) ts.Complete();

                    GenerateResponse(returnValue, context, methodDef, serviceDef);
                }
                catch (Exception x)
                {
                    WebServiceHelper.WriteExceptionJsonString(context, x, serviceDef.Serializer);
                }
                finally
                {
                    // If transaction was started for the method, dispose the transaction. This will
                    // rollback if not committed
                    if( null != ts) ts.Dispose();

                    // Dispose the web service
                    target.Dispose();
                }
            }
        }
Пример #13
0
        private void GenerateResponse(object returnValue, HttpContext context, WebMethodDef methodDef)
        {
            string responseString = null;
            string contentType    = "application/json";

            if (methodDef.ResponseFormat == System.Web.Script.Services.ResponseFormat.Json)
            {
                responseString = _serializer.Serialize(returnValue);
                contentType    = "application/json";
            }
            else if (methodDef.ResponseFormat == System.Web.Script.Services.ResponseFormat.Xml)
            {
                responseString = returnValue as string;
                contentType    = "text/xml";
            }

            context.Response.ContentType = contentType;

            // If we have response and no redirection happening and client still connected, send response
            if (responseString != null && !context.Response.IsRequestBeingRedirected && context.Response.IsClientConnected)
            {
                // Produce proper cache. If no cache information specified on method and there's been no cache related
                // changes done within the web method code, then default cache will be private, no cache.
                if (IsCacheSet(context.Response))
                {
                    // Cache has been modified within the code. So, do not change any cache policy
                }
                else
                {
                    // Cache is still private. Check if there's any CacheDuration set in WebMethod
                    int cacheDuration = methodDef.WebMethodAtt.CacheDuration;
                    if (cacheDuration > 0)
                    {
                        // If CacheDuration attribute is set, use server side caching
                        context.Response.Cache.SetCacheability(HttpCacheability.Server);
                        context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(cacheDuration));
                        context.Response.Cache.SetSlidingExpiration(false);
                        context.Response.Cache.SetValidUntilExpires(true);

                        if (methodDef.InputParameters.Count > 0)
                        {
                            context.Response.Cache.VaryByParams["*"] = true;
                        }
                        else
                        {
                            context.Response.Cache.VaryByParams.IgnoreParams = true;
                        }
                    }
                    else
                    {
                        context.Response.Cache.SetNoServerCaching();
                        context.Response.Cache.SetMaxAge(TimeSpan.Zero);
                    }
                }

                // Convert the response to response encoding, e.g. utf8
                byte[] unicodeBytes = Encoding.Unicode.GetBytes(responseString);
                byte[] utf8Bytes    = Encoding.Convert(Encoding.Unicode, context.Response.ContentEncoding, unicodeBytes);

                // Emit content length in UTF8 encoding string
                context.Response.AppendHeader("Content-Length", utf8Bytes.Length.ToString());

                // Instead of Response.Write which will convert the output to UTF8, use the internal stream
                // to directly write the utf8 bytes
                context.Response.OutputStream.Write(utf8Bytes, 0, utf8Bytes.Length);
            }
            else
            {
                // Send no body as response and we will just abort it
                context.Response.AppendHeader("Content-Length", "0");
                context.Response.ClearContent();
                context.Response.StatusCode = 204; // No Content
            }
        }
Пример #14
0
        /// <summary>
        /// Caches a web method definition 
        /// </summary>
        /// <param name="wsType"></param>
        /// <param name="methods"></param>
        /// <param name="method"></param>
        private void AddMethod(Type wsType, Dictionary<string, WebMethodDef> methods, MethodInfo method)
        {
            object[] wmAttribs = method.GetCustomAttributes(typeof(WebMethodAttribute), false);

            if (wmAttribs.Length == 0)
                return;

            ScriptMethodAttribute sm = null;
            object[] responseAttribs = method.GetCustomAttributes(typeof(ScriptMethodAttribute), false);
            if (responseAttribs.Length > 0)
            {
                sm = (ScriptMethodAttribute)responseAttribs[0];
            }

            TransactionalMethodAttribute tm = null;
            object[] tmAttribs = method.GetCustomAttributes(typeof(TransactionalMethodAttribute), false);
            if (tmAttribs.Length > 0)
            {
                tm = (TransactionalMethodAttribute)tmAttribs[0];
            }

            ETagMethodAttribute em = null;
            object[] emAttribs = method.GetCustomAttributes(typeof(ETagMethodAttribute), false);
            if (emAttribs.Length > 0)
            {
                em = (ETagMethodAttribute)emAttribs[0];
            }

            WebMethodDef wmd = new WebMethodDef(this, method, (WebMethodAttribute)wmAttribs[0], sm, tm, em);
            methods[wmd.MethodName] = wmd;
        }
Пример #15
0
        public WebMethodDef(WebServiceDef wsDef, MethodInfo method, WebMethodAttribute wmAttribute, ScriptMethodAttribute smAttribute, TransactionalMethodAttribute tmAttribute, ETagMethodAttribute emAttribute)
        {
            this.MethodType = method;
            this.WebMethodAtt = wmAttribute;
            this.ScriptMethodAtt = smAttribute;
            this.TransactionAtt = tmAttribute;

            if( null != emAttribute ) this.IsETagEnabled = emAttribute.Enabled;

            if (wmAttribute != null && !string.IsNullOrEmpty(wmAttribute.MessageName)) this.MethodName = wmAttribute.MessageName;
            else this.MethodName = method.Name;

            // HTTP GET method is allowed only when there's a [ScriptMethod] attribute and UseHttpGet is true
            this.IsGetAllowed = (this.ScriptMethodAtt != null && this.ScriptMethodAtt.UseHttpGet);

            this.ResponseFormat = (this.ScriptMethodAtt != null ? this.ScriptMethodAtt.ResponseFormat : ResponseFormat.Json);

            MethodInfo beginMethod = wsDef.WSType.GetMethod("Begin" + method.Name, BINDING_FLAGS);
            if (null != beginMethod)
            {
                // The BeginXXX method must have the [ScriptMethod] attribute
                object[] scriptMethodAttributes = beginMethod.GetCustomAttributes(typeof(ScriptMethodAttribute), false);
                if (scriptMethodAttributes.Length > 0)
                {
                    // Asynchronous methods found for the function
                    this.HasAsyncMethods = true;

                    this.BeginMethod = new WebMethodDef(wsDef, beginMethod, null, null, null, null);

                    MethodInfo endMethod = wsDef.WSType.GetMethod("End" + method.Name, BINDING_FLAGS);
                    this.EndMethod = new WebMethodDef(wsDef, endMethod, null, null, null, null);

                    // get all parameters of begin web method and then leave last two parameters in the input parameters list because
                    // last two parameters are for AsyncCallback and Async State
                    ParameterInfo[] allParameters = beginMethod.GetParameters();
                    ParameterInfo[] inputParameters = new ParameterInfo[allParameters.Length - 2];
                    Array.Copy(allParameters, inputParameters, allParameters.Length - 2);

                    this.BeginMethod.InputParameters = new List<ParameterInfo>(inputParameters);
                    this.BeginMethod.InputParametersWithAsyc = new List<ParameterInfo>(allParameters);
                }
            }

            this.InputParameters = new List<ParameterInfo>(method.GetParameters());
        }