1 //------------------------------------------------------------------------------ 2 // <copyright file="WebReferencesBuildProvider.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 //------------------------------------------------------------------------------ 6 7 namespace System.Web.Compilation { 8 9 using System; 10 using System.Globalization; 11 using System.CodeDom; 12 using System.CodeDom.Compiler; 13 using System.Collections.Specialized; 14 using System.Net; 15 using System.Xml.Serialization; 16 #if !FEATURE_PAL 17 using System.Web.Services.Description; 18 using System.Web.Services.Discovery; 19 #endif // !FEATURE_PAL 20 using System.Web.Hosting; 21 using System.Web.UI; 22 using System.Web.Util; 23 using Util=System.Web.UI.Util; 24 25 internal class WebReferencesBuildProvider: BuildProvider { 26 27 private VirtualDirectory _vdir; 28 29 private const string IndigoWebRefProviderTypeName = "System.Web.Compilation.WCFBuildProvider"; 30 private static Type s_indigoWebRefProviderType; 31 private static bool s_triedToGetWebRefType; 32 WebReferencesBuildProvider(VirtualDirectory vdir)33 internal WebReferencesBuildProvider(VirtualDirectory vdir) { 34 _vdir = vdir; 35 } 36 GenerateCode(AssemblyBuilder assemblyBuilder)37 public override void GenerateCode(AssemblyBuilder assemblyBuilder) { 38 39 // Only attempt to get the Indigo provider once 40 if (!s_triedToGetWebRefType) { 41 s_indigoWebRefProviderType = BuildManager.GetType(IndigoWebRefProviderTypeName, false /*throwOnError*/); 42 s_triedToGetWebRefType = true; 43 } 44 45 // If we have an Indigo provider, instantiate it and forward the GenerateCode call to it 46 if (s_indigoWebRefProviderType != null) { 47 BuildProvider buildProvider = (BuildProvider)HttpRuntime.CreateNonPublicInstance(s_indigoWebRefProviderType); 48 buildProvider.SetVirtualPath(VirtualPathObject); 49 buildProvider.GenerateCode(assemblyBuilder); 50 } 51 52 // e.g "/MyApp/Application_WebReferences" 53 VirtualPath rootWebRefDirVirtualPath = HttpRuntime.WebRefDirectoryVirtualPath; 54 55 // e.g "/MyApp/Application_WebReferences/Foo/Bar" 56 string currentWebRefDirVirtualPath = _vdir.VirtualPath; 57 58 Debug.Assert(StringUtil.StringStartsWithIgnoreCase( 59 currentWebRefDirVirtualPath, rootWebRefDirVirtualPath.VirtualPathString)); 60 61 string ns; 62 63 if (rootWebRefDirVirtualPath.VirtualPathString.Length == currentWebRefDirVirtualPath.Length) { 64 // If it's the root WebReferences dir, use the empty namespace 65 ns = String.Empty; 66 } 67 else { 68 // e.g. "Foo/Bar" 69 Debug.Assert(rootWebRefDirVirtualPath.HasTrailingSlash); 70 currentWebRefDirVirtualPath = UrlPath.RemoveSlashFromPathIfNeeded(currentWebRefDirVirtualPath); 71 currentWebRefDirVirtualPath = currentWebRefDirVirtualPath.Substring( 72 rootWebRefDirVirtualPath.VirtualPathString.Length); 73 74 // Split it into chunks separated by '/' 75 string[] chunks = currentWebRefDirVirtualPath.Split('/'); 76 77 // Turn all the relevant chunks into valid namespace chunks 78 for (int i=0; i<chunks.Length; i++) { 79 chunks[i] = Util.MakeValidTypeNameFromString(chunks[i]); 80 } 81 82 // Put the relevant chunks back together to form the namespace 83 ns = String.Join(".", chunks); 84 } 85 #if !FEATURE_PAL // FEATURE_PAL does not support System.Web.Services 86 87 CodeNamespace codeNamespace = new CodeNamespace(ns); 88 89 // for each discomap file, read all references and add them to the WebReferenceCollection 90 WebReferenceCollection webs = new WebReferenceCollection(); 91 92 bool hasDiscomap = false; 93 94 // Go through all the discomap in the directory 95 foreach (VirtualFile child in _vdir.Files) { 96 97 string extension = UrlPath.GetExtension(child.VirtualPath); 98 extension = extension.ToLower(CultureInfo.InvariantCulture); 99 100 if (extension == ".discomap") { 101 // NOTE: the WebReferences code requires physical path, so this feature 102 // cannot work with a non-file based VirtualPathProvider 103 string physicalPath = HostingEnvironment.MapPath(child.VirtualPath); 104 105 DiscoveryClientProtocol client = new DiscoveryClientProtocol(); 106 client.AllowAutoRedirect = true; 107 client.Credentials = CredentialCache.DefaultCredentials; 108 109 client.ReadAll(physicalPath); 110 111 WebReference webRefTemp = new WebReference(client.Documents, codeNamespace); 112 113 // 114 115 string fileName = System.IO.Path.ChangeExtension(UrlPath.GetFileName(child.VirtualPath), null); 116 string appSetttingUrlKey = ns + "." + fileName; 117 118 WebReference web = new WebReference(client.Documents, codeNamespace, webRefTemp.ProtocolName, appSetttingUrlKey, null); 119 120 webs.Add(web); 121 122 hasDiscomap = true; 123 } 124 } 125 126 // If we didn't find any discomap files, we have nothing to generate 127 if (!hasDiscomap) 128 return; 129 130 CodeCompileUnit codeCompileUnit = new CodeCompileUnit(); 131 codeCompileUnit.Namespaces.Add(codeNamespace); 132 133 //public static StringCollection GenerateWebReferences(WebReferenceCollection webReferences, CodeDomProvider codeProvider, CodeCompileUnit codeCompileUnit, WebReferenceOptions options) { 134 WebReferenceOptions options = new WebReferenceOptions(); 135 options.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync | CodeGenerationOptions.GenerateOldAsync; 136 options.Style = ServiceDescriptionImportStyle.Client; 137 options.Verbose = true; 138 StringCollection shareWarnings = ServiceDescriptionImporter.GenerateWebReferences(webs, assemblyBuilder.CodeDomProvider, codeCompileUnit, options); 139 // Add the CodeCompileUnit to the compilation 140 assemblyBuilder.AddCodeCompileUnit(this, codeCompileUnit); 141 #else // !FEATURE_PAL 142 return; 143 #endif // !FEATURE_PAL 144 } 145 } 146 147 } 148