Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / xsp / System / Web / Extensions / Script / Services / WebServiceData.cs / 2 / WebServiceData.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.Globalization; using System.IO; using System.Reflection; using System.Security; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Web; using System.Web; using System.Web.Caching; using System.Web.Compilation; using System.Web.Configuration; using System.Web.Hosting; using System.Web.Resources; using System.Web.Script.Serialization; using System.Web.Services; using System.Xml; internal class WebServiceData : JavaScriptTypeResolver { private WebServiceTypeData _typeData; private bool _pageMethods; // True for page methods(which only look at static methods) private Dictionary_methods; // this is used to map __type ids in the JSON string to something other than type.FullName private Dictionary _typeResolverSpecials = new Dictionary (); private Dictionary _clientTypesDictionary; private Dictionary _clientTypeNameDictionary; private Dictionary _enumTypesDictionary; private Hashtable _processedTypes; private bool _clientTypesProcessed; private JavaScriptSerializer _serializer; internal JavaScriptSerializer Serializer { get { return _serializer; } } internal const string _profileServiceFileName = "Profile_JSON_AppService.axd"; internal const string _authenticationServiceFileName = "Authentication_JSON_AppService.axd"; internal const string _roleServiceFileName = "Role_JSON_AppService.axd"; private static WebServiceData GetApplicationService(string appRelativePath) { // we only support the application services being accessed at the root level, so that url authorization can be used to control their access. // In other words, "~/Profile_JSON_AppService.axd" should work but not "~/SomeSubDir/Profile_JSON_AppService.axd". // AppRelativeCurrentExecutionFilePath looks like "~/path/filename.ext". // So we can easily detect if the file requested is in the root by ensuring that the last index of "/" is == 1, // as in the path "~/rootfile.ext", where "/" is the second character. // Note that the WebServiceData object is cached higher in the stack once calculated int slashIndex = appRelativePath.LastIndexOf('/'); if (slashIndex == 1) { // it is a root file. Now see if its one of the two built in services string name = Path.GetFileName(appRelativePath); if (name.Equals(_profileServiceFileName, StringComparison.OrdinalIgnoreCase)) { return new WebServiceData(typeof(System.Web.Profile.ProfileService), false); } else if (name.Equals(_authenticationServiceFileName, StringComparison.OrdinalIgnoreCase)) { return new WebServiceData(typeof(System.Web.Security.AuthenticationService), false); } else if (name.Equals(_roleServiceFileName, StringComparison.OrdinalIgnoreCase)) { return new WebServiceData(typeof(System.Web.Security.RoleService), false); } } return null; } internal static WebServiceData GetWebServiceData(HttpContext context, string virtualPath) { return GetWebServiceData(context, virtualPath, true /*failIfNoData*/, false /*pageMethods*/, false/*inlineScript*/); } private static string GetCacheKey(string virtualPath) { return "System.Web.Script.Services.WebServiceData:" + virtualPath; } internal static WebServiceData GetWebServiceData(HttpContext context, string virtualPath, bool failIfNoData, bool pageMethods) { return GetWebServiceData(context, virtualPath, failIfNoData, pageMethods, false /*inlineScript*/); } internal static WebServiceData GetWebServiceData(HttpContext context, string virtualPath, bool failIfNoData, bool pageMethods, bool inlineScript) { // Make sure the path is cannonical to avoid doing more work than necessary virtualPath = VirtualPathUtility.ToAbsolute(virtualPath); string cacheKey = GetCacheKey(virtualPath); WebServiceData data = context.Cache[cacheKey] as WebServiceData; // Handle the case where the virtualPath exists, for example a real asmx page. if (data == null) { if (HostingEnvironment.VirtualPathProvider.FileExists(virtualPath)) { Type compiledType = null; try { compiledType = BuildManager.GetCompiledType(virtualPath); // If we can't get the compiled type, try creating an instance (i.e. for no compile pages) if (compiledType == null) { object page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(System.Web.UI.Page)); if (page != null) { compiledType = page.GetType(); } } } catch (SecurityException) { // DevDiv 33708: BuildManager requires Medium trust, so we need to no-op rather than // destroying the page. } if (compiledType != null) { data = new WebServiceData(compiledType, pageMethods); BuildDependencySet deps = BuildManager.GetCachedBuildDependencySet(context, virtualPath); CacheDependency cd = HostingEnvironment.VirtualPathProvider.GetCacheDependency(virtualPath, deps.VirtualPaths, DateTime.Now); context.Cache.Insert(cacheKey, data, cd); } } else if (virtualPath.EndsWith("_AppService.axd", StringComparison.OrdinalIgnoreCase)) { // File does not exist, but the url may be a request for one of the three built-in services: ProfileService, AuthenticationService, RoleService data = WebServiceData.GetApplicationService(context.Request.AppRelativeCurrentExecutionFilePath); if (data != null) { context.Cache.Insert(cacheKey, data); } } } if (data == null) { if (failIfNoData) { if (inlineScript) { //DevDiv 74432: InlineScript = true fails, for WCF serviceReferences: Need an appropriate error message throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.WebService_NoWebServiceDataInlineScript, virtualPath)); } else { throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.WebService_NoWebServiceData, virtualPath)); } } else { return null; } } return data; } internal static WebServiceData GetWebServiceData(ContractDescription contract) { WebServiceData serviceData = new WebServiceData(); // set service type serviceData._typeData = new WebServiceTypeData(XmlConvert.DecodeName(contract.Name), XmlConvert.DecodeName(contract.Namespace), contract.ContractType); // build list of types used in service Dictionary clientTypeDictionary = new Dictionary (); serviceData._clientTypesDictionary = clientTypeDictionary; Dictionary enumTypeDictionary = new Dictionary (); serviceData._enumTypesDictionary = enumTypeDictionary; serviceData._processedTypes = new Hashtable(); serviceData._clientTypesProcessed = true; serviceData._clientTypeNameDictionary = new Dictionary (); //build method dictionary Dictionary methodDataDictionary = new Dictionary (); serviceData._methods = methodDataDictionary; foreach (OperationDescription operation in contract.Operations) { Dictionary parameterDataDictionary = new Dictionary (); bool useHttpGet = operation.Behaviors.Find () != null; WebServiceMethodData methodData = new WebServiceMethodData(serviceData, XmlConvert.DecodeName(operation.Name), parameterDataDictionary, useHttpGet); // build parameter dictionary MessageDescription requestMessage = operation.Messages[0]; if (requestMessage != null) { int numMessageParts = requestMessage.Body.Parts.Count; for (int p = 0; p < numMessageParts; p++) { MessagePartDescription messagePart = requestMessage.Body.Parts[p]; // DevDiv 129964:JS proxy generation fails for a WCF service that uses an untyped message // Message or its derived class are special, used for untyped operation contracts. // As per the WCF team proxy generated for them should treat Message equivalent to Object type. Type paramType = ReplaceMessageWithObject(messagePart.Type); WebServiceParameterData parameterData = new WebServiceParameterData(XmlConvert.DecodeName(messagePart.Name), paramType, p); parameterDataDictionary[parameterData.ParameterName] = parameterData; serviceData.ProcessClientType(paramType, false, true); } } if (operation.Messages.Count > 1) { // its a two way operation, get type information from return message MessageDescription responseMessage = operation.Messages[1]; if (responseMessage != null) { if (responseMessage.Body.ReturnValue != null && responseMessage.Body.ReturnValue.Type != null) { // operation has a return type, add type to list of type proxy to generate serviceData.ProcessClientType(ReplaceMessageWithObject(responseMessage.Body.ReturnValue.Type), false, true); } } } //add known types at operation level for (int t = 0; t < operation.KnownTypes.Count; t++) { serviceData.ProcessClientType(operation.KnownTypes[t], false, true); } methodDataDictionary[methodData.MethodName] = methodData; } serviceData._processedTypes = null; return serviceData; } private static Type ReplaceMessageWithObject(Type t) { return (typeof(Message).IsAssignableFrom(t)) ? typeof(object) : t; } private WebServiceData() { } private WebServiceData(WebServiceTypeData typeData) { _typeData = typeData; _serializer = new JavaScriptSerializer(this); #pragma warning disable 0436 ScriptingJsonSerializationSection.ApplicationSettings settings = new ScriptingJsonSerializationSection.ApplicationSettings(); #pragma warning restore 0436 _serializer.MaxJsonLength = settings.MaxJsonLimit; _serializer.RecursionLimit = settings.RecursionLimit; _serializer.RegisterConverters(settings.Converters); } // Normal ASMX Atlas codepath for creating webservice data internal WebServiceData(Type type, bool pageMethods) : this(new WebServiceTypeData(type.Name, type.Namespace, type)) { _pageMethods = pageMethods; // Pages don't need to have script service attribute if (!_pageMethods) { object[] attribs = type.GetCustomAttributes(typeof(ScriptServiceAttribute), true); if (attribs.Length == 0) { throw new InvalidOperationException(AtlasWeb.WebService_NoScriptServiceAttribute); } } } // Indigo entry point for creating WebServiceData internal WebServiceData(WebServiceTypeData typeData, Dictionary methods) : this(typeData) { _methods = methods; } private void AddMethod(Dictionary methods, MethodInfo method) { object[] wmAttribs = method.GetCustomAttributes(typeof(WebMethodAttribute), true); // Skip it if it doesn't have the WebMethod attribute if (wmAttribs.Length == 0) return; ScriptMethodAttribute sm = null; object[] responseAttribs = method.GetCustomAttributes(typeof(ScriptMethodAttribute), true); if (responseAttribs.Length > 0) { sm = (ScriptMethodAttribute)responseAttribs[0]; } // Create an object to keep track of this method's data WebServiceMethodData wmd = new WebServiceMethodData(this, method, (WebMethodAttribute)wmAttribs[0], sm); methods[wmd.MethodName] = wmd; } private void EnsureMethods() { // Type will only be null for the Indigo code path if (_methods != null || _typeData.Type == null) return; // Build the method collection on demand lock (this) { // Need to add the methods of each type in reverse order List typeList = new List (); Type current = _typeData.Type; typeList.Add(current); while (current.BaseType != null) { current = current.BaseType; typeList.Add(current); } Dictionary methods = new Dictionary (StringComparer.OrdinalIgnoreCase); BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly; if (_pageMethods) flags |= BindingFlags.Static; else flags |= BindingFlags.Instance; // Add the methods in reverse order from base to derived for (int i = typeList.Count - 1; i >= 0; --i) { MethodInfo[] methodInfos = typeList[i].GetMethods(flags); foreach (MethodInfo method in methodInfos) { AddMethod(methods, method); } } _methods = methods; } } internal WebServiceTypeData TypeData { get { return _typeData; } } internal ICollection MethodDatas { get { EnsureMethods(); return _methods.Values; } } internal WebServiceMethodData GetMethodData(string methodName) { EnsureMethods(); // Fail if the web method doesn't exist WebServiceMethodData methodData = null; if (!_methods.TryGetValue(methodName, out methodData)) { throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_UnknownWebMethod, methodName), "methodName"); } EnsureClientTypesProcessed(); return methodData; } private void EnsureClientTypesProcessed() { if (_clientTypesProcessed) return; lock (this) { if (_clientTypesProcessed) return; ProcessClientTypes(); } } private void ProcessClientTypes() { Debug.Assert(!_clientTypesProcessed, "ProcessClientTypes shouldn't be called after it has already been successfully run."); // List of types that can be instantiated on the client _clientTypesDictionary = new Dictionary (); _enumTypesDictionary = new Dictionary (); _clientTypeNameDictionary = new Dictionary (); try { // _processedTypes is used to avoid processing a Type more than once _processedTypes = new Hashtable(); // Process any GenerateScriptTypes on the Service type ProcessIncludeAttributes((GenerateScriptTypeAttribute[])_typeData.Type.GetCustomAttributes(typeof(GenerateScriptTypeAttribute), true)); foreach (WebServiceMethodData methodData in MethodDatas) { // Process any GenerateScriptTypes on the method ProcessIncludeAttributes((GenerateScriptTypeAttribute[])methodData.MethodInfo.GetCustomAttributes(typeof(GenerateScriptTypeAttribute), true)); // Also add any input parameters foreach (WebServiceParameterData paramData in methodData.ParameterDatas) { ProcessClientType(paramData.ParameterInfo.ParameterType); } // Ignore return type if it uses XML instead of JSON if (methodData.UseXmlResponse) continue; ProcessClientType(methodData.ReturnType); } // DevDiv 60672: Only set to true if the proxies were SUCCESSFULLY processed // Only setting _clientTypesProcessed=true on success will cause us to retry creating the proxies each // request when there is an exception, and so the same exception will be thrown each time. _clientTypesProcessed = true; } catch { // If we have any exception we have to null out our caches _clientTypesDictionary = null; _enumTypesDictionary = null; _clientTypeNameDictionary = null; throw; } finally { _processedTypes = null; } } private void ProcessIncludeAttributes(GenerateScriptTypeAttribute[] attributes) { foreach (GenerateScriptTypeAttribute attribute in attributes) { if (!String.IsNullOrEmpty(attribute.ScriptTypeId)) _typeResolverSpecials[attribute.Type.FullName] = attribute.ScriptTypeId; Type t = attribute.Type; if (t.IsPrimitive || t == typeof(object) || t == typeof(string) || t == typeof(DateTime) || t == typeof(Guid) || typeof(IEnumerable).IsAssignableFrom(t) || typeof(IDictionary).IsAssignableFrom(t) || (t.IsGenericType && t.GetGenericArguments().Length > 1) || !ObjectConverter.IsClientInstantiatableType(t, _serializer)) throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.WebService_InvalidGenerateScriptType, t.FullName)); ProcessClientType(t, true); } } private void ProcessClientType(Type t) { ProcessClientType(t, false, false); } private void ProcessClientType(Type t, bool force) { ProcessClientType(t, force, false); } // Force = true is required for when we detect a GenerateScriptType which may supply a new ScriptTypeID private void ProcessClientType(Type t, bool force, bool isWCF) { if (!force && _processedTypes.Contains(t)) return; _processedTypes[t] = null; // Keep track of all enum Types if (t.IsEnum) { WebServiceEnumData enumData = null; if (isWCF) { enumData = (WebServiceEnumData)WebServiceTypeData.GetWebServiceTypeData(t); } else { enumData = new WebServiceEnumData(t.Name, t.Namespace, t, Enum.GetNames(t), Enum.GetValues(t), Enum.GetUnderlyingType(t) == typeof(ulong)); } _enumTypesDictionary[GetTypeStringRepresentation(enumData.TypeName, false)] = enumData; return; } // For generics, we only allow generic types with one parameter, which we will try to process if (t.IsGenericType) { if (isWCF) { ProcessKnownTypes(t); } else { Type[] genericArgs = t.GetGenericArguments(); if (genericArgs.Length > 1) { return; } ProcessClientType(genericArgs[0], false, isWCF); } } // Support arrays explicitly else if (t.IsArray) { ProcessClientType(t.GetElementType(), false, isWCF); } else { // Ignore primitive types // Ignore DateTime, since we have special serialization handling for it in the JavaScriptSerializer // Ignore IDctionary and IEnumerables as well if (t.IsPrimitive || t == typeof(object) || t == typeof(string) || t == typeof(DateTime) || t == typeof(void) || t == typeof(System.Decimal) || t == typeof(Guid) || typeof(IEnumerable).IsAssignableFrom(t) || typeof(IDictionary).IsAssignableFrom(t) || (!isWCF && !ObjectConverter.IsClientInstantiatableType(t, _serializer))) return; // Only add it to the list of client types if it can be instantiated. // pass false to skip the lock if (isWCF) { ProcessKnownTypes(t); } else { string typeStringRepresentation = GetTypeStringRepresentation(t.FullName, false); _clientTypesDictionary[typeStringRepresentation] = new WebServiceTypeData(t.Name, t.Namespace, t); _clientTypeNameDictionary[t] = typeStringRepresentation; } } } private void ProcessKnownTypes(Type t) { WebServiceTypeData typeData = WebServiceTypeData.GetWebServiceTypeData(t); bool alreadyProcessed = false; if (typeData == null) { // indicates a type was used that is a built-in type return; } // if T implments IEnumerable or IDictionary, do not include type proxy for it // but still continue to get known types. I.e List should ignore List // but process MyType if (!(typeof(IEnumerable).IsAssignableFrom(t) || typeof(IDictionary).IsAssignableFrom(t))) { _clientTypeNameDictionary[t] = GetTypeStringRepresentation(typeData.TypeName); alreadyProcessed = ProcessTypeData(typeData); } if (!alreadyProcessed) { IList knownTypes = WebServiceTypeData.GetKnownTypes(t, typeData); foreach (WebServiceTypeData knownType in knownTypes) { ProcessTypeData(knownType); } } } // returns true if typeData already exists in typeDictionary private bool ProcessTypeData(WebServiceTypeData typeData) { string typeString = GetTypeStringRepresentation(typeData.TypeName); bool retval = true; if (typeData is WebServiceEnumData) { if (!_enumTypesDictionary.ContainsKey(typeString)) { _enumTypesDictionary[typeString] = (WebServiceEnumData)typeData; retval = false; } } else { if (!_clientTypesDictionary.ContainsKey(typeString)) { _clientTypesDictionary[typeString] = typeData; retval = false; } } return retval; } internal IEnumerable ClientTypes { get { return ClientTypeDictionary.Values; } } internal Dictionary ClientTypeDictionary { get { EnsureClientTypesProcessed(); return _clientTypesDictionary; } set { _clientTypesDictionary = value; } } internal Dictionary ClientTypeNameDictionary { get { EnsureClientTypesProcessed(); return _clientTypeNameDictionary; } } internal IEnumerable EnumTypes { get { EnsureClientTypesProcessed(); return _enumTypesDictionary.Values; } } internal Dictionary EnumTypeDictionary { get { EnsureClientTypesProcessed(); return _enumTypesDictionary; } set { _enumTypesDictionary = value; } } public override Type ResolveType(string id) { WebServiceTypeData type = null; if (ClientTypeDictionary.TryGetValue(id, out type)) { if (type != null) { return type.Type; } } return null; } public override string ResolveTypeId(Type type) { string typeString = GetTypeStringRepresentation(type.FullName); // If this type is not in the dictionary if (!ClientTypeDictionary.ContainsKey(typeString)) return null; return typeString; } internal string GetTypeStringRepresentation(string typeName) { return GetTypeStringRepresentation(typeName, true); } internal string GetTypeStringRepresentation(string typeName, bool ensure) { if (ensure) { EnsureClientTypesProcessed(); } // Handle special cases from GenerateScriptType first string typeString; if (_typeResolverSpecials.TryGetValue(typeName, out typeString)) { return typeString; } return typeName; } internal string GetTypeStringRepresentation(WebServiceTypeData typeData) { //First check if typeData provides its string representaiton ( for WCF case) string typeString = typeData.StringRepresentation; if (typeString == null) { typeString = GetTypeStringRepresentation(typeData.TypeName, true); } return typeString; } } } // 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.Globalization; using System.IO; using System.Reflection; using System.Security; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Web; using System.Web; using System.Web.Caching; using System.Web.Compilation; using System.Web.Configuration; using System.Web.Hosting; using System.Web.Resources; using System.Web.Script.Serialization; using System.Web.Services; using System.Xml; internal class WebServiceData : JavaScriptTypeResolver { private WebServiceTypeData _typeData; private bool _pageMethods; // True for page methods(which only look at static methods) private Dictionary_methods; // this is used to map __type ids in the JSON string to something other than type.FullName private Dictionary _typeResolverSpecials = new Dictionary (); private Dictionary _clientTypesDictionary; private Dictionary _clientTypeNameDictionary; private Dictionary _enumTypesDictionary; private Hashtable _processedTypes; private bool _clientTypesProcessed; private JavaScriptSerializer _serializer; internal JavaScriptSerializer Serializer { get { return _serializer; } } internal const string _profileServiceFileName = "Profile_JSON_AppService.axd"; internal const string _authenticationServiceFileName = "Authentication_JSON_AppService.axd"; internal const string _roleServiceFileName = "Role_JSON_AppService.axd"; private static WebServiceData GetApplicationService(string appRelativePath) { // we only support the application services being accessed at the root level, so that url authorization can be used to control their access. // In other words, "~/Profile_JSON_AppService.axd" should work but not "~/SomeSubDir/Profile_JSON_AppService.axd". // AppRelativeCurrentExecutionFilePath looks like "~/path/filename.ext". // So we can easily detect if the file requested is in the root by ensuring that the last index of "/" is == 1, // as in the path "~/rootfile.ext", where "/" is the second character. // Note that the WebServiceData object is cached higher in the stack once calculated int slashIndex = appRelativePath.LastIndexOf('/'); if (slashIndex == 1) { // it is a root file. Now see if its one of the two built in services string name = Path.GetFileName(appRelativePath); if (name.Equals(_profileServiceFileName, StringComparison.OrdinalIgnoreCase)) { return new WebServiceData(typeof(System.Web.Profile.ProfileService), false); } else if (name.Equals(_authenticationServiceFileName, StringComparison.OrdinalIgnoreCase)) { return new WebServiceData(typeof(System.Web.Security.AuthenticationService), false); } else if (name.Equals(_roleServiceFileName, StringComparison.OrdinalIgnoreCase)) { return new WebServiceData(typeof(System.Web.Security.RoleService), false); } } return null; } internal static WebServiceData GetWebServiceData(HttpContext context, string virtualPath) { return GetWebServiceData(context, virtualPath, true /*failIfNoData*/, false /*pageMethods*/, false/*inlineScript*/); } private static string GetCacheKey(string virtualPath) { return "System.Web.Script.Services.WebServiceData:" + virtualPath; } internal static WebServiceData GetWebServiceData(HttpContext context, string virtualPath, bool failIfNoData, bool pageMethods) { return GetWebServiceData(context, virtualPath, failIfNoData, pageMethods, false /*inlineScript*/); } internal static WebServiceData GetWebServiceData(HttpContext context, string virtualPath, bool failIfNoData, bool pageMethods, bool inlineScript) { // Make sure the path is cannonical to avoid doing more work than necessary virtualPath = VirtualPathUtility.ToAbsolute(virtualPath); string cacheKey = GetCacheKey(virtualPath); WebServiceData data = context.Cache[cacheKey] as WebServiceData; // Handle the case where the virtualPath exists, for example a real asmx page. if (data == null) { if (HostingEnvironment.VirtualPathProvider.FileExists(virtualPath)) { Type compiledType = null; try { compiledType = BuildManager.GetCompiledType(virtualPath); // If we can't get the compiled type, try creating an instance (i.e. for no compile pages) if (compiledType == null) { object page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(System.Web.UI.Page)); if (page != null) { compiledType = page.GetType(); } } } catch (SecurityException) { // DevDiv 33708: BuildManager requires Medium trust, so we need to no-op rather than // destroying the page. } if (compiledType != null) { data = new WebServiceData(compiledType, pageMethods); BuildDependencySet deps = BuildManager.GetCachedBuildDependencySet(context, virtualPath); CacheDependency cd = HostingEnvironment.VirtualPathProvider.GetCacheDependency(virtualPath, deps.VirtualPaths, DateTime.Now); context.Cache.Insert(cacheKey, data, cd); } } else if (virtualPath.EndsWith("_AppService.axd", StringComparison.OrdinalIgnoreCase)) { // File does not exist, but the url may be a request for one of the three built-in services: ProfileService, AuthenticationService, RoleService data = WebServiceData.GetApplicationService(context.Request.AppRelativeCurrentExecutionFilePath); if (data != null) { context.Cache.Insert(cacheKey, data); } } } if (data == null) { if (failIfNoData) { if (inlineScript) { //DevDiv 74432: InlineScript = true fails, for WCF serviceReferences: Need an appropriate error message throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.WebService_NoWebServiceDataInlineScript, virtualPath)); } else { throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.WebService_NoWebServiceData, virtualPath)); } } else { return null; } } return data; } internal static WebServiceData GetWebServiceData(ContractDescription contract) { WebServiceData serviceData = new WebServiceData(); // set service type serviceData._typeData = new WebServiceTypeData(XmlConvert.DecodeName(contract.Name), XmlConvert.DecodeName(contract.Namespace), contract.ContractType); // build list of types used in service Dictionary clientTypeDictionary = new Dictionary (); serviceData._clientTypesDictionary = clientTypeDictionary; Dictionary enumTypeDictionary = new Dictionary (); serviceData._enumTypesDictionary = enumTypeDictionary; serviceData._processedTypes = new Hashtable(); serviceData._clientTypesProcessed = true; serviceData._clientTypeNameDictionary = new Dictionary (); //build method dictionary Dictionary methodDataDictionary = new Dictionary (); serviceData._methods = methodDataDictionary; foreach (OperationDescription operation in contract.Operations) { Dictionary parameterDataDictionary = new Dictionary (); bool useHttpGet = operation.Behaviors.Find () != null; WebServiceMethodData methodData = new WebServiceMethodData(serviceData, XmlConvert.DecodeName(operation.Name), parameterDataDictionary, useHttpGet); // build parameter dictionary MessageDescription requestMessage = operation.Messages[0]; if (requestMessage != null) { int numMessageParts = requestMessage.Body.Parts.Count; for (int p = 0; p < numMessageParts; p++) { MessagePartDescription messagePart = requestMessage.Body.Parts[p]; // DevDiv 129964:JS proxy generation fails for a WCF service that uses an untyped message // Message or its derived class are special, used for untyped operation contracts. // As per the WCF team proxy generated for them should treat Message equivalent to Object type. Type paramType = ReplaceMessageWithObject(messagePart.Type); WebServiceParameterData parameterData = new WebServiceParameterData(XmlConvert.DecodeName(messagePart.Name), paramType, p); parameterDataDictionary[parameterData.ParameterName] = parameterData; serviceData.ProcessClientType(paramType, false, true); } } if (operation.Messages.Count > 1) { // its a two way operation, get type information from return message MessageDescription responseMessage = operation.Messages[1]; if (responseMessage != null) { if (responseMessage.Body.ReturnValue != null && responseMessage.Body.ReturnValue.Type != null) { // operation has a return type, add type to list of type proxy to generate serviceData.ProcessClientType(ReplaceMessageWithObject(responseMessage.Body.ReturnValue.Type), false, true); } } } //add known types at operation level for (int t = 0; t < operation.KnownTypes.Count; t++) { serviceData.ProcessClientType(operation.KnownTypes[t], false, true); } methodDataDictionary[methodData.MethodName] = methodData; } serviceData._processedTypes = null; return serviceData; } private static Type ReplaceMessageWithObject(Type t) { return (typeof(Message).IsAssignableFrom(t)) ? typeof(object) : t; } private WebServiceData() { } private WebServiceData(WebServiceTypeData typeData) { _typeData = typeData; _serializer = new JavaScriptSerializer(this); #pragma warning disable 0436 ScriptingJsonSerializationSection.ApplicationSettings settings = new ScriptingJsonSerializationSection.ApplicationSettings(); #pragma warning restore 0436 _serializer.MaxJsonLength = settings.MaxJsonLimit; _serializer.RecursionLimit = settings.RecursionLimit; _serializer.RegisterConverters(settings.Converters); } // Normal ASMX Atlas codepath for creating webservice data internal WebServiceData(Type type, bool pageMethods) : this(new WebServiceTypeData(type.Name, type.Namespace, type)) { _pageMethods = pageMethods; // Pages don't need to have script service attribute if (!_pageMethods) { object[] attribs = type.GetCustomAttributes(typeof(ScriptServiceAttribute), true); if (attribs.Length == 0) { throw new InvalidOperationException(AtlasWeb.WebService_NoScriptServiceAttribute); } } } // Indigo entry point for creating WebServiceData internal WebServiceData(WebServiceTypeData typeData, Dictionary methods) : this(typeData) { _methods = methods; } private void AddMethod(Dictionary methods, MethodInfo method) { object[] wmAttribs = method.GetCustomAttributes(typeof(WebMethodAttribute), true); // Skip it if it doesn't have the WebMethod attribute if (wmAttribs.Length == 0) return; ScriptMethodAttribute sm = null; object[] responseAttribs = method.GetCustomAttributes(typeof(ScriptMethodAttribute), true); if (responseAttribs.Length > 0) { sm = (ScriptMethodAttribute)responseAttribs[0]; } // Create an object to keep track of this method's data WebServiceMethodData wmd = new WebServiceMethodData(this, method, (WebMethodAttribute)wmAttribs[0], sm); methods[wmd.MethodName] = wmd; } private void EnsureMethods() { // Type will only be null for the Indigo code path if (_methods != null || _typeData.Type == null) return; // Build the method collection on demand lock (this) { // Need to add the methods of each type in reverse order List typeList = new List (); Type current = _typeData.Type; typeList.Add(current); while (current.BaseType != null) { current = current.BaseType; typeList.Add(current); } Dictionary methods = new Dictionary (StringComparer.OrdinalIgnoreCase); BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly; if (_pageMethods) flags |= BindingFlags.Static; else flags |= BindingFlags.Instance; // Add the methods in reverse order from base to derived for (int i = typeList.Count - 1; i >= 0; --i) { MethodInfo[] methodInfos = typeList[i].GetMethods(flags); foreach (MethodInfo method in methodInfos) { AddMethod(methods, method); } } _methods = methods; } } internal WebServiceTypeData TypeData { get { return _typeData; } } internal ICollection MethodDatas { get { EnsureMethods(); return _methods.Values; } } internal WebServiceMethodData GetMethodData(string methodName) { EnsureMethods(); // Fail if the web method doesn't exist WebServiceMethodData methodData = null; if (!_methods.TryGetValue(methodName, out methodData)) { throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, AtlasWeb.WebService_UnknownWebMethod, methodName), "methodName"); } EnsureClientTypesProcessed(); return methodData; } private void EnsureClientTypesProcessed() { if (_clientTypesProcessed) return; lock (this) { if (_clientTypesProcessed) return; ProcessClientTypes(); } } private void ProcessClientTypes() { Debug.Assert(!_clientTypesProcessed, "ProcessClientTypes shouldn't be called after it has already been successfully run."); // List of types that can be instantiated on the client _clientTypesDictionary = new Dictionary (); _enumTypesDictionary = new Dictionary (); _clientTypeNameDictionary = new Dictionary (); try { // _processedTypes is used to avoid processing a Type more than once _processedTypes = new Hashtable(); // Process any GenerateScriptTypes on the Service type ProcessIncludeAttributes((GenerateScriptTypeAttribute[])_typeData.Type.GetCustomAttributes(typeof(GenerateScriptTypeAttribute), true)); foreach (WebServiceMethodData methodData in MethodDatas) { // Process any GenerateScriptTypes on the method ProcessIncludeAttributes((GenerateScriptTypeAttribute[])methodData.MethodInfo.GetCustomAttributes(typeof(GenerateScriptTypeAttribute), true)); // Also add any input parameters foreach (WebServiceParameterData paramData in methodData.ParameterDatas) { ProcessClientType(paramData.ParameterInfo.ParameterType); } // Ignore return type if it uses XML instead of JSON if (methodData.UseXmlResponse) continue; ProcessClientType(methodData.ReturnType); } // DevDiv 60672: Only set to true if the proxies were SUCCESSFULLY processed // Only setting _clientTypesProcessed=true on success will cause us to retry creating the proxies each // request when there is an exception, and so the same exception will be thrown each time. _clientTypesProcessed = true; } catch { // If we have any exception we have to null out our caches _clientTypesDictionary = null; _enumTypesDictionary = null; _clientTypeNameDictionary = null; throw; } finally { _processedTypes = null; } } private void ProcessIncludeAttributes(GenerateScriptTypeAttribute[] attributes) { foreach (GenerateScriptTypeAttribute attribute in attributes) { if (!String.IsNullOrEmpty(attribute.ScriptTypeId)) _typeResolverSpecials[attribute.Type.FullName] = attribute.ScriptTypeId; Type t = attribute.Type; if (t.IsPrimitive || t == typeof(object) || t == typeof(string) || t == typeof(DateTime) || t == typeof(Guid) || typeof(IEnumerable).IsAssignableFrom(t) || typeof(IDictionary).IsAssignableFrom(t) || (t.IsGenericType && t.GetGenericArguments().Length > 1) || !ObjectConverter.IsClientInstantiatableType(t, _serializer)) throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.WebService_InvalidGenerateScriptType, t.FullName)); ProcessClientType(t, true); } } private void ProcessClientType(Type t) { ProcessClientType(t, false, false); } private void ProcessClientType(Type t, bool force) { ProcessClientType(t, force, false); } // Force = true is required for when we detect a GenerateScriptType which may supply a new ScriptTypeID private void ProcessClientType(Type t, bool force, bool isWCF) { if (!force && _processedTypes.Contains(t)) return; _processedTypes[t] = null; // Keep track of all enum Types if (t.IsEnum) { WebServiceEnumData enumData = null; if (isWCF) { enumData = (WebServiceEnumData)WebServiceTypeData.GetWebServiceTypeData(t); } else { enumData = new WebServiceEnumData(t.Name, t.Namespace, t, Enum.GetNames(t), Enum.GetValues(t), Enum.GetUnderlyingType(t) == typeof(ulong)); } _enumTypesDictionary[GetTypeStringRepresentation(enumData.TypeName, false)] = enumData; return; } // For generics, we only allow generic types with one parameter, which we will try to process if (t.IsGenericType) { if (isWCF) { ProcessKnownTypes(t); } else { Type[] genericArgs = t.GetGenericArguments(); if (genericArgs.Length > 1) { return; } ProcessClientType(genericArgs[0], false, isWCF); } } // Support arrays explicitly else if (t.IsArray) { ProcessClientType(t.GetElementType(), false, isWCF); } else { // Ignore primitive types // Ignore DateTime, since we have special serialization handling for it in the JavaScriptSerializer // Ignore IDctionary and IEnumerables as well if (t.IsPrimitive || t == typeof(object) || t == typeof(string) || t == typeof(DateTime) || t == typeof(void) || t == typeof(System.Decimal) || t == typeof(Guid) || typeof(IEnumerable).IsAssignableFrom(t) || typeof(IDictionary).IsAssignableFrom(t) || (!isWCF && !ObjectConverter.IsClientInstantiatableType(t, _serializer))) return; // Only add it to the list of client types if it can be instantiated. // pass false to skip the lock if (isWCF) { ProcessKnownTypes(t); } else { string typeStringRepresentation = GetTypeStringRepresentation(t.FullName, false); _clientTypesDictionary[typeStringRepresentation] = new WebServiceTypeData(t.Name, t.Namespace, t); _clientTypeNameDictionary[t] = typeStringRepresentation; } } } private void ProcessKnownTypes(Type t) { WebServiceTypeData typeData = WebServiceTypeData.GetWebServiceTypeData(t); bool alreadyProcessed = false; if (typeData == null) { // indicates a type was used that is a built-in type return; } // if T implments IEnumerable or IDictionary, do not include type proxy for it // but still continue to get known types. I.e List should ignore List // but process MyType if (!(typeof(IEnumerable).IsAssignableFrom(t) || typeof(IDictionary).IsAssignableFrom(t))) { _clientTypeNameDictionary[t] = GetTypeStringRepresentation(typeData.TypeName); alreadyProcessed = ProcessTypeData(typeData); } if (!alreadyProcessed) { IList knownTypes = WebServiceTypeData.GetKnownTypes(t, typeData); foreach (WebServiceTypeData knownType in knownTypes) { ProcessTypeData(knownType); } } } // returns true if typeData already exists in typeDictionary private bool ProcessTypeData(WebServiceTypeData typeData) { string typeString = GetTypeStringRepresentation(typeData.TypeName); bool retval = true; if (typeData is WebServiceEnumData) { if (!_enumTypesDictionary.ContainsKey(typeString)) { _enumTypesDictionary[typeString] = (WebServiceEnumData)typeData; retval = false; } } else { if (!_clientTypesDictionary.ContainsKey(typeString)) { _clientTypesDictionary[typeString] = typeData; retval = false; } } return retval; } internal IEnumerable ClientTypes { get { return ClientTypeDictionary.Values; } } internal Dictionary ClientTypeDictionary { get { EnsureClientTypesProcessed(); return _clientTypesDictionary; } set { _clientTypesDictionary = value; } } internal Dictionary ClientTypeNameDictionary { get { EnsureClientTypesProcessed(); return _clientTypeNameDictionary; } } internal IEnumerable EnumTypes { get { EnsureClientTypesProcessed(); return _enumTypesDictionary.Values; } } internal Dictionary EnumTypeDictionary { get { EnsureClientTypesProcessed(); return _enumTypesDictionary; } set { _enumTypesDictionary = value; } } public override Type ResolveType(string id) { WebServiceTypeData type = null; if (ClientTypeDictionary.TryGetValue(id, out type)) { if (type != null) { return type.Type; } } return null; } public override string ResolveTypeId(Type type) { string typeString = GetTypeStringRepresentation(type.FullName); // If this type is not in the dictionary if (!ClientTypeDictionary.ContainsKey(typeString)) return null; return typeString; } internal string GetTypeStringRepresentation(string typeName) { return GetTypeStringRepresentation(typeName, true); } internal string GetTypeStringRepresentation(string typeName, bool ensure) { if (ensure) { EnsureClientTypesProcessed(); } // Handle special cases from GenerateScriptType first string typeString; if (_typeResolverSpecials.TryGetValue(typeName, out typeString)) { return typeString; } return typeName; } internal string GetTypeStringRepresentation(WebServiceTypeData typeData) { //First check if typeData provides its string representaiton ( for WCF case) string typeString = typeData.StringRepresentation; if (typeString == null) { typeString = GetTypeStringRepresentation(typeData.TypeName, true); } return typeString; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SimpleFieldTemplateUserControl.cs
- Transform.cs
- WindowsTreeView.cs
- InlinedLocationReference.cs
- InputScopeNameConverter.cs
- RootBuilder.cs
- ProfileServiceManager.cs
- StateDesigner.Helpers.cs
- QueryCacheManager.cs
- ScrollViewerAutomationPeer.cs
- XmlBinaryReader.cs
- VisualBrush.cs
- RoleBoolean.cs
- ComponentResourceKey.cs
- ByteStreamMessageEncodingElement.cs
- XmlSerializerVersionAttribute.cs
- NamespaceCollection.cs
- ManagedFilter.cs
- TrustManagerPromptUI.cs
- HtmlElementEventArgs.cs
- DecryptRequest.cs
- EffectiveValueEntry.cs
- ProxyHelper.cs
- ToolboxItemCollection.cs
- ToolBar.cs
- _FixedSizeReader.cs
- OutKeywords.cs
- PtsCache.cs
- SQLDateTime.cs
- WeakEventTable.cs
- Double.cs
- ThemeInfoAttribute.cs
- SqlTriggerAttribute.cs
- ExtensionQuery.cs
- DesignerVerb.cs
- HostedBindingBehavior.cs
- HandlerBase.cs
- XmlIlGenerator.cs
- XmlSchemaSimpleContent.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- Types.cs
- ConfigXmlText.cs
- EmbossBitmapEffect.cs
- NamespaceQuery.cs
- RTLAwareMessageBox.cs
- StickyNoteAnnotations.cs
- EdmRelationshipRoleAttribute.cs
- StringDictionaryEditor.cs
- UnmanagedMemoryStreamWrapper.cs
- UnauthorizedAccessException.cs
- DataGridViewSortCompareEventArgs.cs
- SynchronizationContext.cs
- StrongNameUtility.cs
- XmlWrappingReader.cs
- FileVersionInfo.cs
- FileLevelControlBuilderAttribute.cs
- DataControlFieldCell.cs
- WizardPanel.cs
- SafeMemoryMappedFileHandle.cs
- SafePointer.cs
- DefaultTextStoreTextComposition.cs
- KeysConverter.cs
- SqlClientPermission.cs
- AlignmentXValidation.cs
- DataGridViewCellValidatingEventArgs.cs
- DataObject.cs
- MatrixConverter.cs
- ParagraphResult.cs
- TextTrailingWordEllipsis.cs
- DragDrop.cs
- TextStore.cs
- MainMenu.cs
- ArgumentException.cs
- AssemblyResolver.cs
- Utils.cs
- ContainsRowNumberChecker.cs
- FormatSettings.cs
- CommunicationException.cs
- TransformGroup.cs
- ClientFactory.cs
- EmptyReadOnlyDictionaryInternal.cs
- SafeProcessHandle.cs
- ValidationEventArgs.cs
- DurableDispatcherAddressingFault.cs
- StoryFragments.cs
- ResourceDisplayNameAttribute.cs
- ReferencedCollectionType.cs
- KeyManager.cs
- DirectionalLight.cs
- CodeBlockBuilder.cs
- OdbcCommandBuilder.cs
- HandlerMappingMemo.cs
- MemberInfoSerializationHolder.cs
- HtmlSelectionListAdapter.cs
- PreviousTrackingServiceAttribute.cs
- _emptywebproxy.cs
- StackBuilderSink.cs
- ConfigXmlDocument.cs
- FormViewUpdatedEventArgs.cs
- FileSystemInfo.cs