ClientProxyGenerator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Extensions / Script / Services / ClientProxyGenerator.cs / 1305376 / ClientProxyGenerator.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.Script.Services { 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Text;
    using System.Web;
    using System.Web.Script.Serialization; 

    internal abstract class ClientProxyGenerator { 
        private static string DebugXmlComments = @"///  
/// 
///  
";
        private Hashtable _registeredNamespaces = new Hashtable();
        private Hashtable _ensuredObjectParts = new Hashtable();
        protected StringBuilder _builder; 
        protected bool _debugMode;
        // comments are the same in the instance methods as they are in the static methods 
        // this cache is used when calculating comments for instance methods, then re-used when 
        // writing out static methods.
        private Dictionary _docCommentCache; 

        internal string GetClientProxyScript(WebServiceData webServiceData) {
            if (webServiceData.MethodDatas.Count == 0) return null;
            _builder = new StringBuilder(); 

            if (_debugMode) { 
                _docCommentCache = new Dictionary(); 
            }
 
            // Constructor
            GenerateConstructor(webServiceData);

            // Prototype functions 
            GeneratePrototype(webServiceData);
 
            GenerateRegisterClass(webServiceData); 
            GenerateStaticInstance(webServiceData);
            GenerateStaticMethods(webServiceData); 

            // Generate some client proxy to make some types instantiatable on the client
            GenerateClientTypeProxies(webServiceData);
            GenerateEnumTypeProxies(webServiceData.EnumTypes); 
            return _builder.ToString();
        } 
 
        protected void GenerateRegisterClass(WebServiceData webServiceData) {
            // Generate registerClass: Foo.NS.WebService.registerClass('Foo.NS.WebService', Sys.Net.WebServiceProxy); 
            string typeName = GetProxyTypeName(webServiceData);
            _builder.Append(typeName).Append(".registerClass('").Append(typeName).Append("',Sys.Net.WebServiceProxy);\r\n");
        }
 
        protected virtual void GenerateConstructor(WebServiceData webServiceData) {
            GenerateTypeDeclaration(webServiceData, false); 
            _builder.Append("function() {\r\n"); 
            _builder.Append(GetProxyTypeName(webServiceData)).Append(".initializeBase(this);\r\n");
            GenerateFields(); 
            _builder.Append("}\r\n");
        }

        protected virtual void GeneratePrototype(WebServiceData webServiceData) { 
            GenerateTypeDeclaration(webServiceData, true);
            _builder.Append("{\r\n"); 
            // private method to return the path to be used , returns _path from current instance if set, otherwise returns _path from static instance. 
            _builder.Append("_get_path:function() {\r\n var p = this.get_path();\r\n if (p) return p;\r\n else return ");
            _builder.Append(GetProxyTypeName(webServiceData)).Append("._staticInstance.get_path();},\r\n"); 
            bool first = true;
            foreach (WebServiceMethodData methodData in webServiceData.MethodDatas) {
                if (!first) {
                    _builder.Append(",\r\n"); 
                }
                first = false; 
                GenerateWebMethodProxy(methodData); 
            }
            _builder.Append("}\r\n"); 
        }

        protected virtual void GenerateTypeDeclaration(WebServiceData webServiceData, bool genClass) {
            AppendClientTypeDeclaration(webServiceData.TypeData.TypeNamespace, webServiceData.TypeData.TypeName, genClass, true); 
        }
 
        protected void GenerateFields() { 
            _builder.Append("this._timeout = 0;\r\n");
            _builder.Append("this._userContext = null;\r\n"); 
            _builder.Append("this._succeeded = null;\r\n");
            _builder.Append("this._failed = null;\r\n");
        }
 
        protected virtual void GenerateMethods() {
        } 
 
        protected void GenerateStaticMethods(WebServiceData webServiceData) {
            string className = GetProxyTypeName(webServiceData); 
            // Now generate static methods NS.Service.MyMethod = function()
            foreach (WebServiceMethodData methodData in webServiceData.MethodDatas) {
                string methodName = methodData.MethodName;
                _builder.Append(className).Append('.').Append(methodName).Append("= function("); 
                StringBuilder argBuilder = new StringBuilder();
                bool first = true; 
                foreach (WebServiceParameterData paramData in methodData.ParameterDatas) { 
                    if (!first) argBuilder.Append(',');
                    else first = false; 
                    argBuilder.Append(paramData.ParameterName);
                }
                if (!first) argBuilder.Append(',');
                argBuilder.Append("onSuccess,onFailed,userContext"); 

                _builder.Append(argBuilder.ToString()).Append(") {"); 
 
                if (_debugMode) {
                    // doc comments should have been computed already 
                    _builder.Append("\r\n");
                    _builder.Append(_docCommentCache[methodName]);
                }
 
                _builder.Append(className).Append("._staticInstance.").Append(methodName).Append('(');
                _builder.Append(argBuilder.ToString()).Append("); }\r\n"); 
            } 
        }
 
        protected abstract string GetProxyPath();

        protected virtual string GetJsonpCallbackParameterName() {
            return null; 
        }
 
        protected virtual bool GetSupportsJsonp() { 
            return false;
        } 

        protected void GenerateStaticInstance(WebServiceData data) {
            string typeName = GetProxyTypeName(data);
            _builder.Append(typeName).Append("._staticInstance = new ").Append(typeName).Append("();\r\n"); 

            // Generate the static properties 
            if (_debugMode) { 
                _builder.Append(typeName).Append(".set_path = function(value) {\r\n");
                _builder.Append(typeName).Append("._staticInstance.set_path(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_path = function() { \r\n/// The service url.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_path();}\r\n");

                _builder.Append(typeName).Append(".set_timeout = function(value) {\r\n"); 
                _builder.Append(typeName).Append("._staticInstance.set_timeout(value); }\r\n");
                _builder.Append(typeName).Append(".get_timeout = function() { \r\n/// The service timeout.\r\nreturn "); 
                _builder.Append(typeName).Append("._staticInstance.get_timeout(); }\r\n"); 

                _builder.Append(typeName).Append(".set_defaultUserContext = function(value) { \r\n"); 
                _builder.Append(typeName).Append("._staticInstance.set_defaultUserContext(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultUserContext = function() { \r\n/// The service default user context.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultUserContext(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultSucceededCallback = function(value) { \r\n ");
                _builder.Append(typeName).Append("._staticInstance.set_defaultSucceededCallback(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_defaultSucceededCallback = function() { \r\n/// The service default succeeded callback.\r\nreturn "); 
                _builder.Append(typeName).Append("._staticInstance.get_defaultSucceededCallback(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultFailedCallback = function(value) { \r\n");
                _builder.Append(typeName).Append("._staticInstance.set_defaultFailedCallback(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultFailedCallback = function() { \r\n/// The service default failed callback.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultFailedCallback(); }\r\n"); 

                _builder.Append(typeName).Append(".set_enableJsonp = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_enableJsonp(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_enableJsonp = function() { \r\n/// Specifies whether the service supports JSONP for cross domain calling.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_enableJsonp(); }\r\n"); 

                _builder.Append(typeName).Append(".set_jsonpCallbackParameter = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_jsonpCallbackParameter(value); }\r\n");
                _builder.Append(typeName).Append(".get_jsonpCallbackParameter = function() { \r\n/// Specifies the parameter name that contains the callback function name for a JSONP request.\r\nreturn "); 
                _builder.Append(typeName).Append("._staticInstance.get_jsonpCallbackParameter(); }\r\n");
            } 
            else { 
                _builder.Append(typeName).Append(".set_path = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_path(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_path = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_path(); }\r\n");

                _builder.Append(typeName).Append(".set_timeout = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_timeout(value); }\r\n");
                _builder.Append(typeName).Append(".get_timeout = function() { return "); 
                _builder.Append(typeName).Append("._staticInstance.get_timeout(); }\r\n"); 

                _builder.Append(typeName).Append(".set_defaultUserContext = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_defaultUserContext(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultUserContext = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultUserContext(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultSucceededCallback = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_defaultSucceededCallback(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_defaultSucceededCallback = function() { return "); 
                _builder.Append(typeName).Append("._staticInstance.get_defaultSucceededCallback(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultFailedCallback = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_defaultFailedCallback(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultFailedCallback = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultFailedCallback(); }\r\n"); 

                _builder.Append(typeName).Append(".set_enableJsonp = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_enableJsonp(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_enableJsonp = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_enableJsonp(); }\r\n"); 

                _builder.Append(typeName).Append(".set_jsonpCallbackParameter = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_jsonpCallbackParameter(value); }\r\n");
                _builder.Append(typeName).Append(".get_jsonpCallbackParameter = function() { return "); 
                _builder.Append(typeName).Append("._staticInstance.get_jsonpCallbackParameter(); }\r\n");
            } 
 
            // the path has to be the full absolete path if this is a JSONP enabled service. But it is the responsibility
            // of the caller to GetClientProxyScript to pass the full path if appropriate since determining it may be 
            // dependant on the specific technology.
            _builder.Append(typeName).Append(".set_path(\"").Append(HttpUtility.UrlPathEncode(GetProxyPath())).Append("\");\r\n");
            if (GetSupportsJsonp()) {
                _builder.Append(typeName).Append(".set_enableJsonp(true);\r\n"); 
                string jsonpParameterName = GetJsonpCallbackParameterName();
                if (!String.IsNullOrEmpty(jsonpParameterName) && !jsonpParameterName.Equals("callback", StringComparison.Ordinal)) { 
                    _builder.Append(typeName).Append(".set_jsonpCallbackParameter(").Append(JavaScriptSerializer.SerializeInternal(jsonpParameterName)).Append(");\r\n"); 
                }
            } 
        }

        private  void BuildArgsDictionary(WebServiceMethodData methodData, StringBuilder args, StringBuilder argsDict, StringBuilder docComments) {
            argsDict.Append('{'); 
            foreach (WebServiceParameterData paramData in methodData.ParameterDatas) {
                string name = paramData.ParameterName; 
                if (docComments != null) { 
                    // looks like: /// Namespace.ServerType
                    // client type may not match server type for built in js types like date, number, etc. 
                    // client type may be omitted for type Object.
                    docComments.Append("/// ").Append(serverType.FullName).Append("\r\n");
                } 
                if (args.Length > 0) {
                    args.Append(',');
                    argsDict.Append(',');
                } 
                args.Append(name);
                argsDict.Append(name).Append(':').Append(name); 
            } 
            if (docComments != null) {
                // append the built-in comments that all methods have (success, failed, usercontext parameters) 
                docComments.Append(DebugXmlComments);
            }
            argsDict.Append("}");
            if (args.Length > 0) { 
                args.Append(',');
            } 
            args.Append("succeededCallback, failedCallback, userContext"); 
        }
 
        private void GenerateWebMethodProxy(WebServiceMethodData methodData) {
            string methodName = methodData.MethodName;
            string typeName = GetProxyTypeName(methodData.Owner);
            string useGet = methodData.UseGet ? "true" : "false"; 

            _builder.Append(methodName).Append(':'); 
            // e.g. MyMethod : function(param1, param2, ..., OnSuccess, OnFailure) 
            StringBuilder args = new StringBuilder();
            StringBuilder argsDict = new StringBuilder(); 
            StringBuilder docComments = null;
            string docCommentsString = null;
            if (_debugMode) {
                docComments = new StringBuilder(); 
            }
            BuildArgsDictionary(methodData, args, argsDict, docComments); 
 
            if (_debugMode) {
                // Remember the doc comments for the static instance case 
                docCommentsString = docComments.ToString();
                _docCommentCache[methodName] = docCommentsString;
            }
 
            // Method calls look like this.invoke(FooNS.Sub.Method.get_path(), 'MethodName', true[useGet], {'arg1':'val1', 'arg2':'val2' }, onComplete, onError, userContext, 'FooNS.Sub.Method')
            _builder.Append("function(").Append(args.ToString()).Append(") {\r\n"); 
            if (_debugMode) { 
                // docCommentsString always end in \r\n
                _builder.Append(docCommentsString); 
            }
            _builder.Append("return this._invoke(this._get_path(), ");
            _builder.Append("'").Append(methodName).Append("',");
            _builder.Append(useGet).Append(','); 
            _builder.Append(argsDict.ToString()).Append(",succeededCallback,failedCallback,userContext); }");
        } 
 
        /* e.g
          var Qqq = function() { this.__type = "Qqq"; } 
         */
        private void GenerateClientTypeProxies(WebServiceData data) {
            bool first = true;
            foreach (WebServiceTypeData t in data.ClientTypes) { 
                if (first) {
                    _builder.Append("var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;\r\n"); 
                    first = false; 
                }
 
                string typeID = data.GetTypeStringRepresentation(t);
                string typeNameWithClientNamespace = GetClientTypeNamespace(t.TypeName);
                string typeName = ServicesUtilities.GetClientTypeName(typeNameWithClientNamespace);
                string clientTypeNamespace = GetClientTypeNamespace(t.TypeNamespace); 

                EnsureNamespace(t.TypeNamespace); 
                EnsureObjectGraph(clientTypeNamespace, typeName); 
                _builder.Append("if (typeof(").Append(typeName).Append(") === 'undefined') {\r\n");
                AppendClientTypeDeclaration(clientTypeNamespace, typeNameWithClientNamespace, false, false); 
                // Need to use the _type id, which isn't necessarly the real name
                _builder.Append("gtc(\"");
                _builder.Append(typeID);
                _builder.Append("\");\r\n"); 
                _builder.Append(typeName).Append(".registerClass('").Append(typeName).Append("');\r\n}\r\n");
            } 
        } 

        // Create client stubs for all the enums 
        private void GenerateEnumTypeProxies(IEnumerable enumTypes) {
            foreach (WebServiceEnumData t in enumTypes) {
                EnsureNamespace(t.TypeNamespace);
                string typeNameWithClientNamespace = GetClientTypeNamespace(t.TypeName); 
                string typeName = ServicesUtilities.GetClientTypeName(typeNameWithClientNamespace);
                string[] enumNames = t.Names; 
                long[] enumValues = t.Values; 
                Debug.Assert(enumNames.Length == enumValues.Length);
                EnsureObjectGraph(GetClientTypeNamespace(t.TypeNamespace), typeName); 
                _builder.Append("if (typeof(").Append(typeName).Append(") === 'undefined') {\r\n");
                if (typeName.IndexOf('.') == -1) {
                    _builder.Append("var ");
                } 
                _builder.Append(typeName).Append(" = function() { throw Error.invalidOperation(); }\r\n");
                _builder.Append(typeName).Append(".prototype = {"); 
                for (int i = 0; i < enumNames.Length; i++) { 
                    if (i > 0) _builder.Append(',');
                    _builder.Append(enumNames[i]); 
                    _builder.Append(": ");
                    if (t.IsULong) {
                        _builder.Append((ulong)enumValues[i]);
                    } 
                    else {
                        _builder.Append(enumValues[i]); 
                    } 
                }
                _builder.Append("}\r\n"); 
                _builder.Append(typeName).Append(".registerEnum('").Append(typeName).Append('\'');
                _builder.Append(", true);\r\n}\r\n");
            }
        } 

        protected virtual string GetClientTypeNamespace(string ns) { 
            return ns; 
        }
 
        private void AppendClientTypeDeclaration(string ns, string typeName, bool genClass, bool ensureNS) {
            // Register the namespace if any
            // e.g. registerNamespace('MyNS.MySubNS');
            string name = GetClientTypeNamespace(ServicesUtilities.GetClientTypeName(typeName)); 
            if (!String.IsNullOrEmpty(ns)) {
                if (ensureNS) EnsureNamespace(ns); 
            } 
            else if (!genClass) {
                // If there is no namespace, we need a var to declare the variable 
                if (!name.Contains(".")) {
                    // if name contains '.', an object graph was already ensured and we dont need 'var'.
                    _builder.Append("var ");
                } 
            }
            _builder.Append(name); 
            if (genClass) { 
                _builder.Append(".prototype");
            } 
            _builder.Append('=');
            _ensuredObjectParts[name] = null;
        }
 
        // Normally returns MyNS.MySubNS.MyWebService OR var MyWebService, PageMethods will return PageMethods
        protected virtual string GetProxyTypeName(WebServiceData data) { 
            return ServicesUtilities.GetClientTypeName(data.TypeData.TypeName); 
        }
 
        private void EnsureNamespace(string ns) {
            //Give derived proxy generator a chance to transform namespace ( used by WCF)
            ns = GetClientTypeNamespace(ns);
 
            if (String.IsNullOrEmpty(ns)) return;
 
            // Don't register a given namespace more than once 
            if (!_registeredNamespaces.Contains(ns)) {
                _builder.Append("Type.registerNamespace('").Append(ns).Append("');\r\n"); 
                _registeredNamespaces[ns] = null;
            }
        }
 
        private void EnsureObjectGraph(string namespacePart, string typeName) {
            // When a type name includes dots, such as 'MyNamespace.MyClass.MyNestedClass', 
            // this method writes code that ensures all the parts leading up to the actual class name 
            // are either already namespaces or are at least Objects.
            // namespacePart is here so we dont unnecessarily ensure the first part that contains the 
            // namespace is checked for. For example, if we have NS1.NS2.NS3.TYPE, the check for
            // _registeredNamespaces will find NS1.NS2.NS3 but not NS1 and NS1.NS2, so we'd insert
            // checks that NS1 and NS1.NS2 are objects, unnecessarily.
            int startFrom = 0; 
            bool first = true;
            if (!String.IsNullOrEmpty(namespacePart)) { 
                int nsIndex = typeName.IndexOf(namespacePart + ".", StringComparison.Ordinal); 
                // in wcf services, the typeName starts with the namespace,
                // in asmx services, it doesnt. 
                if (nsIndex > -1) {
                    startFrom = nsIndex + namespacePart.Length + 1;
                    first = false;
                } 
            }
            int dotIndex = typeName.IndexOf('.', startFrom); 
            while (dotIndex > -1) { 
                string fullPath = typeName.Substring(0, dotIndex);
                if (!_registeredNamespaces.Contains(fullPath) && !_ensuredObjectParts.Contains(fullPath)) { 
                    _ensuredObjectParts[fullPath] = null;
                    _builder.Append("if (typeof(" + fullPath + ") === \"undefined\") {\r\n   ");
                    if (first) {
                        // var foo = {}; 
                        _builder.Append("var ");
                        first = false; 
                    } 
                    // foo.bar = {};
                    _builder.Append(fullPath + " = {};\r\n}\r\n"); 
                }
                dotIndex = typeName.IndexOf('.', dotIndex + 1);
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.Script.Services { 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Text;
    using System.Web;
    using System.Web.Script.Serialization; 

    internal abstract class ClientProxyGenerator { 
        private static string DebugXmlComments = @"///  
/// 
///  
";
        private Hashtable _registeredNamespaces = new Hashtable();
        private Hashtable _ensuredObjectParts = new Hashtable();
        protected StringBuilder _builder; 
        protected bool _debugMode;
        // comments are the same in the instance methods as they are in the static methods 
        // this cache is used when calculating comments for instance methods, then re-used when 
        // writing out static methods.
        private Dictionary _docCommentCache; 

        internal string GetClientProxyScript(WebServiceData webServiceData) {
            if (webServiceData.MethodDatas.Count == 0) return null;
            _builder = new StringBuilder(); 

            if (_debugMode) { 
                _docCommentCache = new Dictionary(); 
            }
 
            // Constructor
            GenerateConstructor(webServiceData);

            // Prototype functions 
            GeneratePrototype(webServiceData);
 
            GenerateRegisterClass(webServiceData); 
            GenerateStaticInstance(webServiceData);
            GenerateStaticMethods(webServiceData); 

            // Generate some client proxy to make some types instantiatable on the client
            GenerateClientTypeProxies(webServiceData);
            GenerateEnumTypeProxies(webServiceData.EnumTypes); 
            return _builder.ToString();
        } 
 
        protected void GenerateRegisterClass(WebServiceData webServiceData) {
            // Generate registerClass: Foo.NS.WebService.registerClass('Foo.NS.WebService', Sys.Net.WebServiceProxy); 
            string typeName = GetProxyTypeName(webServiceData);
            _builder.Append(typeName).Append(".registerClass('").Append(typeName).Append("',Sys.Net.WebServiceProxy);\r\n");
        }
 
        protected virtual void GenerateConstructor(WebServiceData webServiceData) {
            GenerateTypeDeclaration(webServiceData, false); 
            _builder.Append("function() {\r\n"); 
            _builder.Append(GetProxyTypeName(webServiceData)).Append(".initializeBase(this);\r\n");
            GenerateFields(); 
            _builder.Append("}\r\n");
        }

        protected virtual void GeneratePrototype(WebServiceData webServiceData) { 
            GenerateTypeDeclaration(webServiceData, true);
            _builder.Append("{\r\n"); 
            // private method to return the path to be used , returns _path from current instance if set, otherwise returns _path from static instance. 
            _builder.Append("_get_path:function() {\r\n var p = this.get_path();\r\n if (p) return p;\r\n else return ");
            _builder.Append(GetProxyTypeName(webServiceData)).Append("._staticInstance.get_path();},\r\n"); 
            bool first = true;
            foreach (WebServiceMethodData methodData in webServiceData.MethodDatas) {
                if (!first) {
                    _builder.Append(",\r\n"); 
                }
                first = false; 
                GenerateWebMethodProxy(methodData); 
            }
            _builder.Append("}\r\n"); 
        }

        protected virtual void GenerateTypeDeclaration(WebServiceData webServiceData, bool genClass) {
            AppendClientTypeDeclaration(webServiceData.TypeData.TypeNamespace, webServiceData.TypeData.TypeName, genClass, true); 
        }
 
        protected void GenerateFields() { 
            _builder.Append("this._timeout = 0;\r\n");
            _builder.Append("this._userContext = null;\r\n"); 
            _builder.Append("this._succeeded = null;\r\n");
            _builder.Append("this._failed = null;\r\n");
        }
 
        protected virtual void GenerateMethods() {
        } 
 
        protected void GenerateStaticMethods(WebServiceData webServiceData) {
            string className = GetProxyTypeName(webServiceData); 
            // Now generate static methods NS.Service.MyMethod = function()
            foreach (WebServiceMethodData methodData in webServiceData.MethodDatas) {
                string methodName = methodData.MethodName;
                _builder.Append(className).Append('.').Append(methodName).Append("= function("); 
                StringBuilder argBuilder = new StringBuilder();
                bool first = true; 
                foreach (WebServiceParameterData paramData in methodData.ParameterDatas) { 
                    if (!first) argBuilder.Append(',');
                    else first = false; 
                    argBuilder.Append(paramData.ParameterName);
                }
                if (!first) argBuilder.Append(',');
                argBuilder.Append("onSuccess,onFailed,userContext"); 

                _builder.Append(argBuilder.ToString()).Append(") {"); 
 
                if (_debugMode) {
                    // doc comments should have been computed already 
                    _builder.Append("\r\n");
                    _builder.Append(_docCommentCache[methodName]);
                }
 
                _builder.Append(className).Append("._staticInstance.").Append(methodName).Append('(');
                _builder.Append(argBuilder.ToString()).Append("); }\r\n"); 
            } 
        }
 
        protected abstract string GetProxyPath();

        protected virtual string GetJsonpCallbackParameterName() {
            return null; 
        }
 
        protected virtual bool GetSupportsJsonp() { 
            return false;
        } 

        protected void GenerateStaticInstance(WebServiceData data) {
            string typeName = GetProxyTypeName(data);
            _builder.Append(typeName).Append("._staticInstance = new ").Append(typeName).Append("();\r\n"); 

            // Generate the static properties 
            if (_debugMode) { 
                _builder.Append(typeName).Append(".set_path = function(value) {\r\n");
                _builder.Append(typeName).Append("._staticInstance.set_path(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_path = function() { \r\n/// The service url.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_path();}\r\n");

                _builder.Append(typeName).Append(".set_timeout = function(value) {\r\n"); 
                _builder.Append(typeName).Append("._staticInstance.set_timeout(value); }\r\n");
                _builder.Append(typeName).Append(".get_timeout = function() { \r\n/// The service timeout.\r\nreturn "); 
                _builder.Append(typeName).Append("._staticInstance.get_timeout(); }\r\n"); 

                _builder.Append(typeName).Append(".set_defaultUserContext = function(value) { \r\n"); 
                _builder.Append(typeName).Append("._staticInstance.set_defaultUserContext(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultUserContext = function() { \r\n/// The service default user context.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultUserContext(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultSucceededCallback = function(value) { \r\n ");
                _builder.Append(typeName).Append("._staticInstance.set_defaultSucceededCallback(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_defaultSucceededCallback = function() { \r\n/// The service default succeeded callback.\r\nreturn "); 
                _builder.Append(typeName).Append("._staticInstance.get_defaultSucceededCallback(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultFailedCallback = function(value) { \r\n");
                _builder.Append(typeName).Append("._staticInstance.set_defaultFailedCallback(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultFailedCallback = function() { \r\n/// The service default failed callback.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultFailedCallback(); }\r\n"); 

                _builder.Append(typeName).Append(".set_enableJsonp = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_enableJsonp(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_enableJsonp = function() { \r\n/// Specifies whether the service supports JSONP for cross domain calling.\r\nreturn ");
                _builder.Append(typeName).Append("._staticInstance.get_enableJsonp(); }\r\n"); 

                _builder.Append(typeName).Append(".set_jsonpCallbackParameter = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_jsonpCallbackParameter(value); }\r\n");
                _builder.Append(typeName).Append(".get_jsonpCallbackParameter = function() { \r\n/// Specifies the parameter name that contains the callback function name for a JSONP request.\r\nreturn "); 
                _builder.Append(typeName).Append("._staticInstance.get_jsonpCallbackParameter(); }\r\n");
            } 
            else { 
                _builder.Append(typeName).Append(".set_path = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_path(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_path = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_path(); }\r\n");

                _builder.Append(typeName).Append(".set_timeout = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_timeout(value); }\r\n");
                _builder.Append(typeName).Append(".get_timeout = function() { return "); 
                _builder.Append(typeName).Append("._staticInstance.get_timeout(); }\r\n"); 

                _builder.Append(typeName).Append(".set_defaultUserContext = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_defaultUserContext(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultUserContext = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultUserContext(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultSucceededCallback = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_defaultSucceededCallback(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_defaultSucceededCallback = function() { return "); 
                _builder.Append(typeName).Append("._staticInstance.get_defaultSucceededCallback(); }\r\n");
 
                _builder.Append(typeName).Append(".set_defaultFailedCallback = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_defaultFailedCallback(value); }\r\n");
                _builder.Append(typeName).Append(".get_defaultFailedCallback = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_defaultFailedCallback(); }\r\n"); 

                _builder.Append(typeName).Append(".set_enableJsonp = function(value) { "); 
                _builder.Append(typeName).Append("._staticInstance.set_enableJsonp(value); }\r\n"); 
                _builder.Append(typeName).Append(".get_enableJsonp = function() { return ");
                _builder.Append(typeName).Append("._staticInstance.get_enableJsonp(); }\r\n"); 

                _builder.Append(typeName).Append(".set_jsonpCallbackParameter = function(value) { ");
                _builder.Append(typeName).Append("._staticInstance.set_jsonpCallbackParameter(value); }\r\n");
                _builder.Append(typeName).Append(".get_jsonpCallbackParameter = function() { return "); 
                _builder.Append(typeName).Append("._staticInstance.get_jsonpCallbackParameter(); }\r\n");
            } 
 
            // the path has to be the full absolete path if this is a JSONP enabled service. But it is the responsibility
            // of the caller to GetClientProxyScript to pass the full path if appropriate since determining it may be 
            // dependant on the specific technology.
            _builder.Append(typeName).Append(".set_path(\"").Append(HttpUtility.UrlPathEncode(GetProxyPath())).Append("\");\r\n");
            if (GetSupportsJsonp()) {
                _builder.Append(typeName).Append(".set_enableJsonp(true);\r\n"); 
                string jsonpParameterName = GetJsonpCallbackParameterName();
                if (!String.IsNullOrEmpty(jsonpParameterName) && !jsonpParameterName.Equals("callback", StringComparison.Ordinal)) { 
                    _builder.Append(typeName).Append(".set_jsonpCallbackParameter(").Append(JavaScriptSerializer.SerializeInternal(jsonpParameterName)).Append(");\r\n"); 
                }
            } 
        }

        private  void BuildArgsDictionary(WebServiceMethodData methodData, StringBuilder args, StringBuilder argsDict, StringBuilder docComments) {
            argsDict.Append('{'); 
            foreach (WebServiceParameterData paramData in methodData.ParameterDatas) {
                string name = paramData.ParameterName; 
                if (docComments != null) { 
                    // looks like: /// Namespace.ServerType
                    // client type may not match server type for built in js types like date, number, etc. 
                    // client type may be omitted for type Object.
                    docComments.Append("/// ").Append(serverType.FullName).Append("\r\n");
                } 
                if (args.Length > 0) {
                    args.Append(',');
                    argsDict.Append(',');
                } 
                args.Append(name);
                argsDict.Append(name).Append(':').Append(name); 
            } 
            if (docComments != null) {
                // append the built-in comments that all methods have (success, failed, usercontext parameters) 
                docComments.Append(DebugXmlComments);
            }
            argsDict.Append("}");
            if (args.Length > 0) { 
                args.Append(',');
            } 
            args.Append("succeededCallback, failedCallback, userContext"); 
        }
 
        private void GenerateWebMethodProxy(WebServiceMethodData methodData) {
            string methodName = methodData.MethodName;
            string typeName = GetProxyTypeName(methodData.Owner);
            string useGet = methodData.UseGet ? "true" : "false"; 

            _builder.Append(methodName).Append(':'); 
            // e.g. MyMethod : function(param1, param2, ..., OnSuccess, OnFailure) 
            StringBuilder args = new StringBuilder();
            StringBuilder argsDict = new StringBuilder(); 
            StringBuilder docComments = null;
            string docCommentsString = null;
            if (_debugMode) {
                docComments = new StringBuilder(); 
            }
            BuildArgsDictionary(methodData, args, argsDict, docComments); 
 
            if (_debugMode) {
                // Remember the doc comments for the static instance case 
                docCommentsString = docComments.ToString();
                _docCommentCache[methodName] = docCommentsString;
            }
 
            // Method calls look like this.invoke(FooNS.Sub.Method.get_path(), 'MethodName', true[useGet], {'arg1':'val1', 'arg2':'val2' }, onComplete, onError, userContext, 'FooNS.Sub.Method')
            _builder.Append("function(").Append(args.ToString()).Append(") {\r\n"); 
            if (_debugMode) { 
                // docCommentsString always end in \r\n
                _builder.Append(docCommentsString); 
            }
            _builder.Append("return this._invoke(this._get_path(), ");
            _builder.Append("'").Append(methodName).Append("',");
            _builder.Append(useGet).Append(','); 
            _builder.Append(argsDict.ToString()).Append(",succeededCallback,failedCallback,userContext); }");
        } 
 
        /* e.g
          var Qqq = function() { this.__type = "Qqq"; } 
         */
        private void GenerateClientTypeProxies(WebServiceData data) {
            bool first = true;
            foreach (WebServiceTypeData t in data.ClientTypes) { 
                if (first) {
                    _builder.Append("var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;\r\n"); 
                    first = false; 
                }
 
                string typeID = data.GetTypeStringRepresentation(t);
                string typeNameWithClientNamespace = GetClientTypeNamespace(t.TypeName);
                string typeName = ServicesUtilities.GetClientTypeName(typeNameWithClientNamespace);
                string clientTypeNamespace = GetClientTypeNamespace(t.TypeNamespace); 

                EnsureNamespace(t.TypeNamespace); 
                EnsureObjectGraph(clientTypeNamespace, typeName); 
                _builder.Append("if (typeof(").Append(typeName).Append(") === 'undefined') {\r\n");
                AppendClientTypeDeclaration(clientTypeNamespace, typeNameWithClientNamespace, false, false); 
                // Need to use the _type id, which isn't necessarly the real name
                _builder.Append("gtc(\"");
                _builder.Append(typeID);
                _builder.Append("\");\r\n"); 
                _builder.Append(typeName).Append(".registerClass('").Append(typeName).Append("');\r\n}\r\n");
            } 
        } 

        // Create client stubs for all the enums 
        private void GenerateEnumTypeProxies(IEnumerable enumTypes) {
            foreach (WebServiceEnumData t in enumTypes) {
                EnsureNamespace(t.TypeNamespace);
                string typeNameWithClientNamespace = GetClientTypeNamespace(t.TypeName); 
                string typeName = ServicesUtilities.GetClientTypeName(typeNameWithClientNamespace);
                string[] enumNames = t.Names; 
                long[] enumValues = t.Values; 
                Debug.Assert(enumNames.Length == enumValues.Length);
                EnsureObjectGraph(GetClientTypeNamespace(t.TypeNamespace), typeName); 
                _builder.Append("if (typeof(").Append(typeName).Append(") === 'undefined') {\r\n");
                if (typeName.IndexOf('.') == -1) {
                    _builder.Append("var ");
                } 
                _builder.Append(typeName).Append(" = function() { throw Error.invalidOperation(); }\r\n");
                _builder.Append(typeName).Append(".prototype = {"); 
                for (int i = 0; i < enumNames.Length; i++) { 
                    if (i > 0) _builder.Append(',');
                    _builder.Append(enumNames[i]); 
                    _builder.Append(": ");
                    if (t.IsULong) {
                        _builder.Append((ulong)enumValues[i]);
                    } 
                    else {
                        _builder.Append(enumValues[i]); 
                    } 
                }
                _builder.Append("}\r\n"); 
                _builder.Append(typeName).Append(".registerEnum('").Append(typeName).Append('\'');
                _builder.Append(", true);\r\n}\r\n");
            }
        } 

        protected virtual string GetClientTypeNamespace(string ns) { 
            return ns; 
        }
 
        private void AppendClientTypeDeclaration(string ns, string typeName, bool genClass, bool ensureNS) {
            // Register the namespace if any
            // e.g. registerNamespace('MyNS.MySubNS');
            string name = GetClientTypeNamespace(ServicesUtilities.GetClientTypeName(typeName)); 
            if (!String.IsNullOrEmpty(ns)) {
                if (ensureNS) EnsureNamespace(ns); 
            } 
            else if (!genClass) {
                // If there is no namespace, we need a var to declare the variable 
                if (!name.Contains(".")) {
                    // if name contains '.', an object graph was already ensured and we dont need 'var'.
                    _builder.Append("var ");
                } 
            }
            _builder.Append(name); 
            if (genClass) { 
                _builder.Append(".prototype");
            } 
            _builder.Append('=');
            _ensuredObjectParts[name] = null;
        }
 
        // Normally returns MyNS.MySubNS.MyWebService OR var MyWebService, PageMethods will return PageMethods
        protected virtual string GetProxyTypeName(WebServiceData data) { 
            return ServicesUtilities.GetClientTypeName(data.TypeData.TypeName); 
        }
 
        private void EnsureNamespace(string ns) {
            //Give derived proxy generator a chance to transform namespace ( used by WCF)
            ns = GetClientTypeNamespace(ns);
 
            if (String.IsNullOrEmpty(ns)) return;
 
            // Don't register a given namespace more than once 
            if (!_registeredNamespaces.Contains(ns)) {
                _builder.Append("Type.registerNamespace('").Append(ns).Append("');\r\n"); 
                _registeredNamespaces[ns] = null;
            }
        }
 
        private void EnsureObjectGraph(string namespacePart, string typeName) {
            // When a type name includes dots, such as 'MyNamespace.MyClass.MyNestedClass', 
            // this method writes code that ensures all the parts leading up to the actual class name 
            // are either already namespaces or are at least Objects.
            // namespacePart is here so we dont unnecessarily ensure the first part that contains the 
            // namespace is checked for. For example, if we have NS1.NS2.NS3.TYPE, the check for
            // _registeredNamespaces will find NS1.NS2.NS3 but not NS1 and NS1.NS2, so we'd insert
            // checks that NS1 and NS1.NS2 are objects, unnecessarily.
            int startFrom = 0; 
            bool first = true;
            if (!String.IsNullOrEmpty(namespacePart)) { 
                int nsIndex = typeName.IndexOf(namespacePart + ".", StringComparison.Ordinal); 
                // in wcf services, the typeName starts with the namespace,
                // in asmx services, it doesnt. 
                if (nsIndex > -1) {
                    startFrom = nsIndex + namespacePart.Length + 1;
                    first = false;
                } 
            }
            int dotIndex = typeName.IndexOf('.', startFrom); 
            while (dotIndex > -1) { 
                string fullPath = typeName.Substring(0, dotIndex);
                if (!_registeredNamespaces.Contains(fullPath) && !_ensuredObjectParts.Contains(fullPath)) { 
                    _ensuredObjectParts[fullPath] = null;
                    _builder.Append("if (typeof(" + fullPath + ") === \"undefined\") {\r\n   ");
                    if (first) {
                        // var foo = {}; 
                        _builder.Append("var ");
                        first = false; 
                    } 
                    // foo.bar = {};
                    _builder.Append(fullPath + " = {};\r\n}\r\n"); 
                }
                dotIndex = typeName.IndexOf('.', dotIndex + 1);
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK