Exemple #1
0
 public void Dispose()
 {
     this.MethodName = null;
     this.Target     = null;
     this.ServiceDef = null;
     this.MethodDef  = null;
     this.Context    = null;
     this.ExtraData  = null;
 }
 public void Dispose()
 {
     this.MethodName = null;
     this.Target = null;
     this.ServiceDef = null;
     this.MethodDef = null;
     this.Context = null;
     this.ExtraData = null;
 }
Exemple #3
0
 public void Dispose()
 {
     MethodName = null;
     Target     = null;
     ServiceDef = null;
     MethodDef  = null;
     Context    = null;
     ExtraData  = null;
 }
Exemple #4
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;
 }
Exemple #5
0
        internal static WebServiceDef GetWebServiceType(HttpContext context, string virtualPath)
        {
            virtualPath = VirtualPathUtility.ToAbsolute(virtualPath.Replace(".soap", ".asmx"));

            string        cacheKey = GetCacheKey(virtualPath);
            WebServiceDef wsType   = context.Cache[cacheKey] as WebServiceDef;

            if (wsType == null)
            {
                if (HostingEnvironment.VirtualPathProvider.FileExists(virtualPath))
                {
                    Type compiledType = null;
                    try
                    {
                        compiledType = BuildManager.GetCompiledType(virtualPath);


                        if (compiledType == null)
                        {
                            object page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(System.Web.UI.Page));
                            compiledType = page.GetType();
                        }
                    }
                    catch (SecurityException)
                    {
                    }

                    if (compiledType != null)
                    {
                        wsType = new WebServiceDef(compiledType);
                        BuildDependencySet deps         = BuildManager.GetCachedBuildDependencySet(context, virtualPath);
                        IEnumerable        virtualPaths = deps.VirtualPaths;
                        if (virtualPaths != null)
                        {
                            List <string> paths = new List <string>();
                            foreach (string path in virtualPaths)
                            {
                                paths.Add(Path.Combine(context.Request.PhysicalApplicationPath, VirtualPathUtility.GetFileName(path)));
                            }
                            context.Cache.Insert(cacheKey, wsType, new CacheDependency(paths.ToArray()));
                        }
                        else
                        {
                            context.Cache.Insert(cacheKey, wsType);
                        }
                    }
                }
            }

            if (wsType == null)
            {
                throw new InvalidOperationException("Webservice does not exist");
            }

            return(wsType);
        }
        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());
        }
 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;
 }
        /// <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();
                }
            }
        }
 public JsonTypeResolver(WebServiceDef def)
 {
     this._serializer = new JavaScriptSerializer(this);
     this._typeData   = def;
 }
        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));
                }
            }
        }
        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
            }
        }
        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
            }
        }
        /// <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();
                }
            }
        }
        internal static WebServiceDef GetWebServiceType(HttpContext context, string virtualPath)
        {
            virtualPath = VirtualPathUtility.ToAbsolute(virtualPath.Replace(".soap", ".asmx"));

            string cacheKey = GetCacheKey(virtualPath);
            WebServiceDef wsType = context.Cache[cacheKey] as WebServiceDef;

            if (wsType == null)
            {
                if (HostingEnvironment.VirtualPathProvider.FileExists(virtualPath))
                {
                    Type compiledType = null;
                    try
                    {
                        compiledType = BuildManager.GetCompiledType(virtualPath);

                        if (compiledType == null)
                        {
                            object page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(System.Web.UI.Page));
                            compiledType = page.GetType();
                        }

                    }
                    catch (SecurityException)
                    {
                    }

                    if (compiledType != null)
                    {
                        wsType = new WebServiceDef(compiledType);
                        BuildDependencySet deps = BuildManager.GetCachedBuildDependencySet(context, virtualPath);
                        IEnumerable virtualPaths = deps.VirtualPaths;
                        if (virtualPaths != null)
                        {
                            List<string> paths = new List<string>();
                            foreach (string path in virtualPaths)
                            {
                                paths.Add(Path.Combine(context.Request.PhysicalApplicationPath, VirtualPathUtility.GetFileName(path)));
                            }
                            context.Cache.Insert(cacheKey, wsType, new CacheDependency(paths.ToArray()));
                        }
                        else
                        {
                            context.Cache.Insert(cacheKey, wsType);
                        }
                    }
                }
            }

            if (wsType == null)
            {
                throw new InvalidOperationException("Webservice does not exist");
            }

            return wsType;
        }
 public JsonTypeResolver(WebServiceDef def)
 {
     this._serializer = new JavaScriptSerializer(this);
     this._typeData = def;
 }
        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());
        }