Browse files

Adding source for the ASP.NET July 2007 Futures:

1.	Bridge
2.	Search
3.	Xml-Script
4.	Diagnostics
5.	ExtractJSFromAssembly



git-svn-id: https://aspnet.svn.codeplex.com/svn@22907 e17a0e51-4ae3-4d35-97c3-1a29b211df97
  • Loading branch information...
1 parent 2afae2a commit 2f96d942b08c7c6a37a2e8a0171961e35cc0a0db SND\AspNetExtensions_cp committed Apr 7, 2009
Showing with 19,492 additions and 0 deletions.
  1. +84 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Microsoft.Web.Preview.Bridge.csproj
  2. +20 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Microsoft.Web.Preview.Bridge.sln
  3. +29 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Properties/AssemblyInfo35.cs
  4. +135 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Resources/PreviewWeb.Designer.cs
  5. +144 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Resources/PreviewWeb.resx
  6. +309 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeBuildProvider.cs
  7. +89 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeCache.cs
  8. +62 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeContext.cs
  9. +320 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeHandler.cs
  10. +39 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeModule.cs
  11. +55 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeRequest.cs
  12. +15 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeResponse.cs
  13. +49 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeRestProxy.cs
  14. +605 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeService.cs
  15. +12 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/IBridgeRequestCache.cs
  16. +6 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/IBridgeResponseTransformer.cs
  17. +50 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/ObjectMapperBridgeTransformer.cs
  18. +34 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/ServiceRequest.cs
  19. +17 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/ServiceResponse.cs
  20. +57 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/XPathBridgeTransformer.cs
  21. +28 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/XmlBridgeTransformer.cs
  22. +42 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/XsltBridgeTransformer.cs
  23. +20 −0 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Util/NGenWrapper.cs
  24. +19 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Configuration/PreviewSectionGroup.cs
  25. +22 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Configuration/SearchSection.cs
  26. +27 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Configuration/SearchSiteMapSection.cs
  27. +127 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Micorosft.Web.Preview.Search.csproj
  28. +20 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Micorosft.Web.Preview.Search.sln
  29. +25 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Properties/AssemblyInfo35.cs
  30. +36 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Properties/Settings.Designer.cs
  31. +9 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Properties/Settings.settings
  32. +90 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Resources/PreviewWeb.Designer.cs
  33. +129 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Resources/PreviewWeb.resx
  34. +58 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/AspNetSiteMapSearchSiteMapProvider.cs
  35. +238 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/DynamicDataSearchSiteMapProvider.cs
  36. BIN AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchDataSource.bmp
  37. +28 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchDataSource.cs
  38. +13 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchProviderBase.cs
  39. +15 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchQuery.cs
  40. +29 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchResult.cs
  41. +66 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchService.cs
  42. +137 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchSiteMapHandler.cs
  43. +37 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/SearchSiteMapProviderBase.cs
  44. +118 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Search/WindowsLiveSearchProvider.cs
  45. +1,653 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Web References/com.msn.search.soap/Reference.cs
  46. +6 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Web References/com.msn.search.soap/Reference.map
  47. +10 −0 .../July 2007 Futures/AtlasSearchPublic/Web References/com.msn.search.soap/SearchResponse.datasource
  48. +286 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/Web References/com.msn.search.soap/webservices.wsdl
  49. +16 −0 AJAX/Futures/July 2007 Futures/AtlasSearchPublic/app.config
  50. +120 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Microsoft.Web.Preview.csproj
  51. +20 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Microsoft.Web.Preview.sln
  52. +49 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Properties/AssemblyInfo35.cs
  53. +126 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Resources/PreviewWeb.Designer.cs
  54. +141 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Resources/PreviewWeb.resx
  55. +1,665 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewDragDrop.debug.js
  56. +6 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewDragDrop.js
  57. +880 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewGlitz.debug.js
  58. +6 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewGlitz.js
  59. +7,507 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewScript.debug.js
  60. +6 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewScript.js
  61. +235 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewWebParts.debug.js
  62. +6 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/PreviewWebParts.js
  63. +35 −0 ...Futures/July 2007 Futures/AtlasValueAddPublic/Script/Serialization/Converters/DataRowConverter.cs
  64. +37 −0 ...Futures/July 2007 Futures/AtlasValueAddPublic/Script/Serialization/Converters/DataSetConverter.cs
  65. +113 −0 ...tures/July 2007 Futures/AtlasValueAddPublic/Script/Serialization/Converters/DataTableConverter.cs
  66. +618 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/WebParts.debug.js
  67. +6 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Script/WebParts.js
  68. +78 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/BaseTypedDictionary.cs
  69. +36 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/ChangeList.cs
  70. +91 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/DataAdapterAttribute.cs
  71. +468 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/DataService.cs
  72. +47 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/ObjectDictionary.cs
  73. +41 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/TypedDictionary.cs
  74. +44 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/Services/XmlDictionary.cs
  75. +8 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/UI/Controls/WebParts/IWebPartZone.cs
  76. BIN AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/UI/Controls/WebParts/WebPartManager.bmp
  77. +105 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/UI/Controls/WebParts/WebPartManager.cs
  78. BIN AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/UI/Controls/WebParts/WebPartZone.bmp
  79. +162 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/UI/Controls/WebParts/WebPartZone.cs
  80. +9 −0 AJAX/Futures/July 2007 Futures/AtlasValueAddPublic/UI/FrameworkScript.cs
  81. +17 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Configuration/DiagnosticsSection.cs
  82. +15 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Configuration/DiagnosticsSectionGroup.cs
  83. +17 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/ClientExceptionEventArgs.cs
  84. BIN AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/Diagnostics.bmp
  85. +79 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/DiagnosticsControl.cs
  86. +24 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/DiagnosticsHandler.cs
  87. +65 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/DiagnosticsService.cs
  88. +31 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/ExceptionInfo.cs
  89. +25 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/ExceptionServerInfo.cs
  90. +13 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Diagnostics/TraceInfo.cs
  91. +83 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Microsoft.Web.Preview.Diagnostics.csproj
  92. +20 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Microsoft.Web.Preview.Diagnostics.sln
  93. +32 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Properties/AssemblyInfo.cs
  94. +72 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Resources/PreviewWeb.Designer.cs
  95. +123 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Resources/PreviewWeb.resx
  96. +114 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Script/Diagnostics.debug.js
  97. +6 −0 AJAX/Futures/July 2007 Futures/DiagnosticsPublic/Script/Diagnostics.js
  98. +57 −0 AJAX/Futures/July 2007 Futures/ExtractJSFromAssembly/ExtractJsFromAssembly.csproj
  99. +18 −0 AJAX/Futures/July 2007 Futures/ExtractJSFromAssembly/ExtractJsFromAssembly.sln
  100. +516 −0 AJAX/Futures/July 2007 Futures/ExtractJSFromAssembly/Program.cs
  101. +33 −0 AJAX/Futures/July 2007 Futures/ExtractJSFromAssembly/Properties/AssemblyInfo.cs
  102. +32 −0 AJAX/Futures/July 2007 Futures/ExtractJSFromAssembly/ScriptResourceInfo.cs
View
84 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Microsoft.Web.Preview.Bridge.csproj
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{77BB5F02-DCAF-4E48-A2FB-6E77E1707784}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Web.Preview</RootNamespace>
+ <AssemblyName>Microsoft.Web.Preview.Bridge</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Extensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo35.cs" />
+ <Compile Include="Resources\PreviewWeb.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>PreviewWeb.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Services\BridgeBuildProvider.cs" />
+ <Compile Include="Services\BridgeCache.cs" />
+ <Compile Include="Services\BridgeContext.cs" />
+ <Compile Include="Services\BridgeHandler.cs" />
+ <Compile Include="Services\BridgeModule.cs" />
+ <Compile Include="Services\BridgeRequest.cs" />
+ <Compile Include="Services\BridgeResponse.cs" />
+ <Compile Include="Services\BridgeRestProxy.cs" />
+ <Compile Include="Services\BridgeService.cs" />
+ <Compile Include="Services\IBridgeRequestCache.cs" />
+ <Compile Include="Services\IBridgeResponseTransformer.cs" />
+ <Compile Include="Services\ObjectMapperBridgeTransformer.cs" />
+ <Compile Include="Services\ServiceRequest.cs" />
+ <Compile Include="Services\ServiceResponse.cs" />
+ <Compile Include="Services\XmlBridgeTransformer.cs" />
+ <Compile Include="Services\XPathBridgeTransformer.cs" />
+ <Compile Include="Services\XsltBridgeTransformer.cs" />
+ <Compile Include="Util\NGenWrapper.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\PreviewWeb.resx">
+ <LastGenOutput>PreviewWeb.Designer.cs</LastGenOutput>
+ <Generator>ResXFileCodeGenerator</Generator>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
20 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Microsoft.Web.Preview.Bridge.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Web.Preview.Bridge", "Microsoft.Web.Preview.Bridge.csproj", "{77BB5F02-DCAF-4E48-A2FB-6E77E1707784}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {77BB5F02-DCAF-4E48-A2FB-6E77E1707784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77BB5F02-DCAF-4E48-A2FB-6E77E1707784}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77BB5F02-DCAF-4E48-A2FB-6E77E1707784}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77BB5F02-DCAF-4E48-A2FB-6E77E1707784}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
View
29 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Properties/AssemblyInfo35.cs
@@ -0,0 +1,29 @@
+// AssemblyInfo.cs
+//
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Web.UI;
+
+[assembly: AssemblyTitle("Microsoft.Web.Preview.Bridge for .NET 3.5")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft Corporation")]
+[assembly: AssemblyProduct("Microsoft.Web.Preview")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: NeutralResourcesLanguage("en", UltimateResourceFallbackLocation.MainAssembly)]
+
+[assembly: AssemblyVersion("2.0.21022.0")]
+[assembly: AssemblyFileVersion("2.0.21022.0")]
+
+[assembly: ComVisible(false)]
+[assembly: CLSCompliant(true)]
View
135 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Resources/PreviewWeb.Designer.cs
@@ -0,0 +1,135 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1434
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Web.Preview.Resources {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class PreviewWeb {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal PreviewWeb() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Web.Preview.Resources.PreviewWeb", typeof(PreviewWeb).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Unable to create BridgeHandler type for: {0}.
+ /// </summary>
+ internal static string BridgeHandler_CannotCreate {
+ get {
+ return ResourceManager.GetString("BridgeHandler_CannotCreate", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Unable to load BridgeHandler type for: {0}.
+ /// </summary>
+ internal static string BridgeHandler_CannotLoad {
+ get {
+ return ResourceManager.GetString("BridgeHandler_CannotLoad", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to BridgeRestProxy: passed a null or empty URL..
+ /// </summary>
+ internal static string BridgeRestProxy_EmptyUrl {
+ get {
+ return ResourceManager.GetString("BridgeRestProxy_EmptyUrl", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to &lt;{0}&gt; node required..
+ /// </summary>
+ internal static string BridgeService_NodeRequired {
+ get {
+ return ResourceManager.GetString("BridgeService_NodeRequired", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to XPathBridgeTransformer requires a selectedNodes dictionary..
+ /// </summary>
+ internal static string XPathBridgeTransformer_RequiresSelectNodes {
+ get {
+ return ResourceManager.GetString("XPathBridgeTransformer_RequiresSelectNodes", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to XPathBridgeTransformer requires a selector attribute..
+ /// </summary>
+ internal static string XPathBridgeTransformer_RequiresSelectorAttribute {
+ get {
+ return ResourceManager.GetString("XPathBridgeTransformer_RequiresSelectorAttribute", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to XPathBridgeTransformer can only transform a string..
+ /// </summary>
+ internal static string XPathBridgeTransformer_StringOnly {
+ get {
+ return ResourceManager.GetString("XPathBridgeTransformer_StringOnly", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to XsltBridgeTransformer can only transform a string..
+ /// </summary>
+ internal static string XsltBridgeTransformer_StringOnly {
+ get {
+ return ResourceManager.GetString("XsltBridgeTransformer_StringOnly", resourceCulture);
+ }
+ }
+ }
+}
View
144 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Resources/PreviewWeb.resx
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="BridgeHandler_CannotCreate" xml:space="preserve">
+ <value>Unable to create BridgeHandler type for: {0}</value>
+ </data>
+ <data name="BridgeHandler_CannotLoad" xml:space="preserve">
+ <value>Unable to load BridgeHandler type for: {0}</value>
+ </data>
+ <data name="BridgeRestProxy_EmptyUrl" xml:space="preserve">
+ <value>BridgeRestProxy: passed a null or empty URL.</value>
+ </data>
+ <data name="BridgeService_NodeRequired" xml:space="preserve">
+ <value>&lt;{0}&gt; node required.</value>
+ </data>
+ <data name="XPathBridgeTransformer_RequiresSelectNodes" xml:space="preserve">
+ <value>XPathBridgeTransformer requires a selectedNodes dictionary.</value>
+ </data>
+ <data name="XPathBridgeTransformer_RequiresSelectorAttribute" xml:space="preserve">
+ <value>XPathBridgeTransformer requires a selector attribute.</value>
+ </data>
+ <data name="XPathBridgeTransformer_StringOnly" xml:space="preserve">
+ <value>XPathBridgeTransformer can only transform a string.</value>
+ </data>
+ <data name="XsltBridgeTransformer_StringOnly" xml:space="preserve">
+ <value>XsltBridgeTransformer can only transform a string.</value>
+ </data>
+</root>
View
309 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeBuildProvider.cs
@@ -0,0 +1,309 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.CodeDom;
+ using System.CodeDom.Compiler;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Net;
+ using System.Reflection;
+ using System.Web;
+ using System.Web.Compilation;
+ using System.Web.Script.Services;
+ using System.Web.Services;
+ using Microsoft.Web.Util;
+
+ class BridgeBuildProvider : BuildProvider {
+ // Store the xml push it into the file for reparsing later
+ private string _bridgeXml = String.Empty;
+
+ private BridgeService _service;
+ protected BridgeService Service {
+ get {
+ if (_service == null) {
+ using (Stream stream = OpenStream(VirtualPath)) {
+ using (TextReader reader = new StreamReader(stream)) {
+ _bridgeXml = reader.ReadToEnd();
+ }
+ }
+
+ if (String.IsNullOrEmpty(_bridgeXml))
+ throw new InvalidOperationException("ASBX file contents are empty");
+
+ _service = new BridgeService(_bridgeXml);
+
+ // Update the service cache
+ BridgeService.UpdateCache(VirtualPath, _service);
+ }
+ return _service;
+ }
+ }
+
+ public BridgeBuildProvider() {
+ }
+
+ public override CompilerType CodeCompilerType {
+ get {
+ return GetDefaultCompilerTypeForLanguage(Service.Language);
+ }
+ }
+
+ public override System.Collections.ICollection VirtualPathDependencies {
+ get {
+ List<string> depedencies = new List<string>(2);
+ depedencies.Add(VirtualPath);
+ if (!string.IsNullOrEmpty(Service.PartialClassFile))
+ depedencies.Add(Service.PartialClassFile);
+ return depedencies;
+ }
+ }
+
+ /*
+ * Line 12: namespace Hao.Kung.Samples {
+ Line 13: using System;
+ Line 14: using System.Net;
+ Line 15: using System.Web.Services;
+ Line 16: using System.Collections;
+ Line 17: using System.Xml.Serialization;
+ Line 18: using System.Web.Services;
+ Line 19:
+ Line 20:
+ Line 21: [WebService(Name="http://tempuri.org/")]
+ Line 22: [WebServiceBinding(ConformsTo=System.Web.Services.WsiProfiles.BasicProfile1_1)]
+ Line 23: public partial class MSNSearch {
+ Line 24:
+ Line 25: public MSNSearch() {
+ Line 26: this.VirtualPath = "/atlas/BCL/msn.asbx";
+ this.BridgeXml = <contents of MSN.asbx>
+ Line 27: }
+ Line 28: [System.Web.Script.Services.ScriptService()]
+ Line 29: [System.Web.Services.WebMethodAttribute()]
+ Line 30: [System.Xml.Serialization.XmlIncludeAttribute(typeof(MSN.SearchRequest))]
+ Line 31: public object Search(System.Collections.IDictionary args) {
+ Line 32: return this.Invoke(new System.Web.Services.BridgeRequest("Search", args));
+ Line 33: }
+ Line 34:
+ */
+ public override void GenerateCode(AssemblyBuilder assemBuilder) {
+ CodeNamespace ns = new CodeNamespace(Service.Namespace);
+ ns.Imports.Add(new CodeNamespaceImport("System"));
+ ns.Imports.Add(new CodeNamespaceImport("System.Net"));
+ ns.Imports.Add(new CodeNamespaceImport("System.Web.Services"));
+ ns.Imports.Add(new CodeNamespaceImport("System.Collections"));
+ ns.Imports.Add(new CodeNamespaceImport("System.Xml.Serialization"));
+ ns.Imports.Add(new CodeNamespaceImport("Microsoft.Web.Preview.Services"));
+ ns.Imports.Add(new CodeNamespaceImport("System.Web.Script.Services"));
+
+ CodeCompileUnit unit = new CodeCompileUnit();
+ unit.Namespaces.Add(ns);
+
+ CodeTypeDeclaration classType = new CodeTypeDeclaration(Service.Classname);
+ classType.BaseTypes.Add(typeof(BridgeHandler));
+ classType.IsPartial = true;
+ ns.Types.Add(classType);
+ classType.CustomAttributes.Add(new CodeAttributeDeclaration("ScriptService"));
+ classType.CustomAttributes.Add(new CodeAttributeDeclaration("WebService", new CodeAttributeArgument("Name", new CodePrimitiveExpression("http://tempuri.org/"))));
+ classType.CustomAttributes.Add(new CodeAttributeDeclaration("WebServiceBinding", new CodeAttributeArgument("ConformsTo", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(WsiProfiles)), "BasicProfile1_1"))));
+
+ /**
+ * public ClassName() {
+ * VirtualPath = <the virtual path>
+ * }
+ */
+ CodeConstructor constructor = new CodeConstructor();
+ constructor.Attributes = MemberAttributes.Public;
+ constructor.Statements.Add(new CodeAssignStatement(
+ new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "VirtualPath"),
+ new CodePrimitiveExpression(VirtualPath)));
+ constructor.Statements.Add(new CodeAssignStatement(
+ new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "BridgeXml"),
+ new CodePrimitiveExpression(_bridgeXml)));
+ classType.Members.Add(constructor);
+
+ ServiceInfo serviceInfo = Service.ServiceInfo;
+ foreach (BridgeMethodInfo methodInfo in serviceInfo.Methods.Values) {
+ classType.Members.Add(GenerateWebMethodCode(methodInfo.Name, methodInfo.XmlIncludes, methodInfo.GetEnabled, methodInfo.ResponseFormat, false));
+ }
+
+ // Skip the proxy method code generation for REST
+ if (!string.Equals(serviceInfo.ServiceClass, "Microsoft.Web.Preview.Services.BridgeRestProxy"))
+ classType.Members.Add(GenerateProxyMethodCode());
+
+ // BridgeMethod hook
+ classType.Members.Add(GenerateWebMethodCode("__invokeBridge", null, false, ResponseFormat.Json, true));
+
+ assemBuilder.AddCodeCompileUnit(this, unit);
+ if (!string.IsNullOrEmpty(Service.PartialClassFile)) {
+ using (TextReader reader = OpenReader(Service.PartialClassFile)) {
+ CodeSnippetCompileUnit snippet = new CodeSnippetCompileUnit(reader.ReadToEnd());
+ if (HttpContext.Current != null) {
+ snippet.LinePragma = new CodeLinePragma(HttpContext.Current.Request.MapPath(Service.PartialClassFile), 1);
+ }
+ assemBuilder.AddCodeCompileUnit(this, snippet);
+ }
+ }
+ }
+
+ /**
+ * public virtual object CallServiceClassMethod(string method, Dictionary<string, object> args, ICredentials credentials, string serviceUrl) {
+ * if (method.Equals("method")) {
+ * ServiceProxy proxy = new ServiceProxy();
+ * proxy.Url = serviceUrl (if Proxy has a Url property)
+ * proxy.Credentials = credentials (if Proxy has a Credentials property)
+ * object arg = args[paramInfo.ServiceName];
+ * ArgType1 arg1;
+ * if (arg is argType1) arg1 = (ArgType1)arg;
+ * return new Proxy().Method1(arg1, arg2, ...);
+ */
+ private CodeMemberMethod GenerateProxyMethodCode() {
+ CodeMemberMethod method = new CodeMemberMethod();
+ method.Attributes = MemberAttributes.Override | MemberAttributes.Public;
+ method.Name = "CallServiceClassMethod";
+ method.ReturnType = new CodeTypeReference(typeof(object));
+ method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "method"));
+ method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Dictionary<String, object>), "args"));
+ method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ICredentials), "credentials"));
+ method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "url"));
+
+ // Prevent duplicate methods, as many bridge methods can map to the same server call
+ Dictionary<string, NGenWrapper<bool>> methodMap = new Dictionary<string, NGenWrapper<bool>>();
+ Type serviceType = BridgeService.GetType(_service.ServiceInfo.ServiceClass);
+ foreach (BridgeMethodInfo methodInfo in _service.ServiceInfo.Methods.Values) {
+ if (methodMap.ContainsKey(methodInfo.ServerName))
+ continue;
+
+ methodMap[methodInfo.ServerName] = true;
+
+ MethodInfo serviceMethodInfo = serviceType.GetMethod(methodInfo.ServerName);
+ if (serviceMethodInfo == null) {
+ throw new ArgumentException("No such method on service proxy class: " + methodInfo.ServerName);
+ }
+ ParameterInfo[] paramData = serviceMethodInfo.GetParameters();
+
+ // if (method == "Method1"
+ CodeConditionStatement ifStmt = new CodeConditionStatement();
+ ifStmt.Condition = new CodeMethodInvokeExpression(new CodePrimitiveExpression(methodInfo.ServerName), "Equals", new CodeArgumentReferenceExpression("method"));
+ // <ServiceClass> proxy = new <ServiceClass>()
+ ifStmt.TrueStatements.Add(new CodeVariableDeclarationStatement(serviceType, "proxy"));
+ ifStmt.TrueStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("proxy"), new CodeObjectCreateExpression(serviceType)));
+
+ // check if the proxy class has a Credentials property
+ PropertyInfo credProp = serviceType.GetProperty("Credentials");
+ if (credProp != null) {
+ // proxy.Credentials = credentials;
+ CodeConditionStatement ifCredNotNull = new CodeConditionStatement();
+ ifCredNotNull.Condition = new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("credentials"), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
+ ifCredNotNull.TrueStatements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("proxy"), "Credentials"), new CodeVariableReferenceExpression("credentials")));
+ ifStmt.TrueStatements.Add(ifCredNotNull);
+ }
+
+ // check if the proxy class has a Url property
+ PropertyInfo urlProp = serviceType.GetProperty("Url");
+ if (urlProp != null) {
+ // proxy.Credentials = credentials;
+ CodeConditionStatement ifUrlNotEmpty = new CodeConditionStatement();
+ ifUrlNotEmpty.Condition = new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(string)), "IsNullOrEmpty"), new CodeVariableReferenceExpression("url"));
+ ifUrlNotEmpty.FalseStatements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("proxy"), "Url"), new CodeVariableReferenceExpression("url")));
+ ifStmt.TrueStatements.Add(ifUrlNotEmpty);
+ }
+
+ // object obj holder for args dictionary lookup
+ ifStmt.TrueStatements.Add(new CodeVariableDeclarationStatement(typeof(object), "obj"));
+
+ // <method>(ConvertValue(arg1, argType1...), ConvertValue(arg2, argType1...), ...)
+ CodeMethodInvokeExpression methodCallExpr = new CodeMethodInvokeExpression();
+ methodCallExpr.Method = new CodeMethodReferenceExpression(new CodeVariableReferenceExpression("proxy"), methodInfo.ServerName);
+ for (int i = 0; i < paramData.Length; ++i) {
+ Type argType = paramData[i].ParameterType;
+ string argName = "arg" + i;
+
+ // ArgTypeN argN
+ ifStmt.TrueStatements.Add(new CodeVariableDeclarationStatement(argType, argName));
+
+ // if (!Dict<name>.TryGet(argName, argn)) throw new ArgumentException()
+ CodeConditionStatement findArgStmt = new CodeConditionStatement();
+ findArgStmt.Condition = new CodeMethodInvokeExpression(new CodeArgumentReferenceExpression("args"),
+ "TryGetValue",
+ new CodePrimitiveExpression(paramData[i].Name),
+ new CodeDirectionExpression(FieldDirection.Out, new CodeVariableReferenceExpression("obj")));
+ findArgStmt.FalseStatements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(ArgumentException),
+ new CodePrimitiveExpression("Argument not found: " + paramData[i].Name))));
+ ifStmt.TrueStatements.Add(findArgStmt);
+
+ // argn = (argtype)ConvertToType(obj, argtype, "paramname");
+ ifStmt.TrueStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(argName),
+ new CodeCastExpression(argType, new CodeMethodInvokeExpression(new CodeSnippetExpression("BridgeHandler"),
+ "ConvertToType",
+ new CodeVariableReferenceExpression("obj"),
+ new CodeTypeOfExpression(argType)))));
+
+ // Build up the arg1, arg2, argn for the method call;
+ methodCallExpr.Parameters.Add(new CodeVariableReferenceExpression(argName));
+ }
+
+ ifStmt.TrueStatements.Add(new CodeMethodReturnStatement(methodCallExpr));
+
+ method.Statements.Add(ifStmt);
+ }
+ method.Statements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(ArgumentException),
+ new CodePrimitiveExpression("CallServiceClassMethod: Unknown method"))));
+ return method;
+ }
+
+ /*
+ * [WebMethod]
+ * [ScriptMethod(UseHttpGet=true,ResponseFormat=ResponseFormat.Json|Xml)]
+ * [XmlInclude(typeof<>) ...
+ * public object Method(IDictionary args) {
+ * return Invoke(new BridgeRequest("Method", args);
+ * }
+ *
+ * __invokeBridge takes the method as an argument
+ */
+ private static CodeMemberMethod GenerateWebMethodCode(String methodName, List<string> xmlIncludes, bool getEnabled, ResponseFormat responseFormat, bool invokeBridge) {
+ CodeMemberMethod method = new CodeMemberMethod();
+ method.Attributes = MemberAttributes.Public;
+ method.Name = methodName;
+ method.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(WebMethodAttribute))));
+
+ string format = "Json";
+ if (responseFormat != ResponseFormat.Json) {
+ format = "Xml";
+ }
+ CodeAttributeDeclaration webOp = new CodeAttributeDeclaration(new CodeTypeReference(typeof(ScriptMethodAttribute)),
+ new CodeAttributeArgument("UseHttpGet", new CodePrimitiveExpression(getEnabled)),
+ new CodeAttributeArgument("ResponseFormat", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(ResponseFormat)), format)));
+ method.CustomAttributes.Add(webOp);
+
+ if (invokeBridge) {
+ method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "method"));
+ }
+ else {
+ for (int i = 0; i < xmlIncludes.Count; ++i) {
+ method.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(GenerateScriptTypeAttribute)),
+ new CodeAttributeArgument(new CodeTypeOfExpression(xmlIncludes[i]))));
+ }
+ }
+
+ method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(IDictionary), "args"));
+
+ method.ReturnType = new CodeTypeReference(typeof(object));
+ CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression();
+ expr.Method = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), "Invoke");
+ CodeExpression methodExpr = null;
+ if (invokeBridge) {
+ methodExpr = new CodeVariableReferenceExpression("method");
+ }
+ else {
+ methodExpr = new CodePrimitiveExpression(methodName);
+ }
+ expr.Parameters.Add(new CodeObjectCreateExpression(typeof(BridgeRequest), methodExpr, new CodeVariableReferenceExpression("args")));
+ method.Statements.Add(new CodeMethodReturnStatement(expr));
+ return method;
+ }
+
+ public override Type GetGeneratedType(CompilerResults results) {
+ return results.CompiledAssembly.GetType(Service.Namespace + "." + Service.Classname);
+ }
+ }
+}
View
89 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeCache.cs
@@ -0,0 +1,89 @@
+namespace Microsoft.Web.Preview.Services {
+ using System.Collections;
+ using System.Collections.Generic;
+ using Microsoft.Web.Util;
+
+ public class BridgeCache : IBridgeRequestCache {
+ private static Dictionary<NGenWrapper<long>, object> _cache = new Dictionary<NGenWrapper<long>, object>();
+
+ public void Initialize(BridgeTransformData data) { }
+
+ public void Clear() {
+ _cache.Clear();
+ }
+
+ public object Lookup(BridgeContext context) {
+ object result = null;
+ if (_cache.TryGetValue(GetCacheKey(context), out result)) {
+ return result;
+ }
+ return null;
+ }
+
+ public void Put(BridgeContext context) {
+ _cache[GetCacheKey(context)] = context.BridgeResponse.Response;
+ }
+
+ // Generate hash from Method and all args
+ private long GetCacheKey(BridgeContext context) {
+ HashCodeCombiner hasher = new HashCodeCombiner();
+
+ hasher.AddObject(context.BridgeUrl);
+ hasher.AddObject(context.ServiceRequest.Method);
+ ComputeHashCode(context.ServiceRequest.Args, hasher);
+
+ return hasher.CombinedHash;
+ }
+
+ // Need to recursively shred dictionaries collections, arrays
+ private void ComputeHashCode(object obj, HashCodeCombiner hasher) {
+ IDictionary dict = obj as IDictionary;
+ if (dict != null) {
+ foreach (object key in dict.Keys) {
+ hasher.AddObject(key);
+ ComputeHashCode(dict[key], hasher);
+ }
+ }
+ else {
+ IEnumerable en = obj as IEnumerable;
+ if ((en != null) && !(obj is string)) {
+ foreach (object o in en) {
+ ComputeHashCode(o, hasher);
+ }
+ }
+ else {
+ hasher.AddObject(obj);
+ }
+ }
+ }
+ }
+
+ /*
+ * Class used to combine several hashcodes into a single hashcode
+ */
+ internal class HashCodeCombiner {
+
+ private long _combinedHash;
+
+ internal HashCodeCombiner() {
+ // Start with a seed (obtained from String.GetHashCode implementation)
+ _combinedHash = 5381;
+ }
+
+ internal void AddInt(int n) {
+ _combinedHash = ((_combinedHash << 5) + _combinedHash) ^ n;
+ }
+
+ internal void AddObject(string s) {
+ if (s != null)
+ AddInt(s.GetHashCode());
+ }
+
+ internal void AddObject(object o) {
+ if (o != null)
+ AddInt(o.GetHashCode());
+ }
+
+ internal long CombinedHash { get { return _combinedHash; } }
+ }
+}
View
62 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeContext.cs
@@ -0,0 +1,62 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+
+ public class BridgeContext {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "Consistency.")]
+ public BridgeContext(BridgeRequest request, string bridgeUrl) {
+ if (request == null) {
+ throw new ArgumentNullException("request");
+ }
+ _request = request;
+ _bridgeUrl = bridgeUrl;
+ }
+
+ // ClientScript request
+ BridgeRequest _request;
+ public BridgeRequest BridgeRequest {
+ get {
+ return _request;
+ }
+ }
+
+ private string _bridgeUrl;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Consistency.")]
+ public string BridgeUrl {
+ get {
+ return _bridgeUrl;
+ }
+ }
+
+ Dictionary<string, object> _resultsChain = new Dictionary<string, object>();
+ public Dictionary<string, object> ResultsChain {
+ get {
+ return _resultsChain;
+ }
+ }
+
+ // Request that will be made to the bridged service
+ ServiceRequest _serviceRequest = new ServiceRequest();
+ public ServiceRequest ServiceRequest {
+ get {
+ return _serviceRequest;
+ }
+ }
+
+ // Final response back to clientscript
+ BridgeResponse _response = new BridgeResponse();
+ public BridgeResponse BridgeResponse {
+ get {
+ return _response;
+ }
+ }
+
+ // Response from the bridged service
+ ServiceResponse _serviceResponse = new ServiceResponse();
+ public ServiceResponse ServiceResponse {
+ get {
+ return _serviceResponse;
+ }
+ }
+ }
+}
View
320 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeHandler.cs
@@ -0,0 +1,320 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Net;
+ using System.Reflection;
+ using System.Web;
+ using System.Web.Compilation;
+ using System.Web.Configuration;
+ using System.Web.Script.Serialization;
+ using System.Web.UI;
+ using Microsoft.Web.Preview.Resources;
+
+ public class BridgeHandler {
+ private BridgeContext _context;
+ protected BridgeContext Context {
+ get {
+ if (_context == null) {
+ throw new InvalidOperationException("Accessing context too early, it is null");
+ }
+ return _context;
+ }
+ }
+
+ protected BridgeRequest BridgeRequest {
+ get {
+ return Context.BridgeRequest;
+ }
+ }
+
+ protected BridgeResponse BridgeResponse {
+ get {
+ return Context.BridgeResponse;
+ }
+ }
+
+ protected ServiceRequest ServiceRequest {
+ get {
+ return Context.ServiceRequest;
+ }
+ }
+
+ protected ServiceResponse ServiceResponse {
+ get {
+ return Context.ServiceResponse;
+ }
+ }
+
+ private string _bridgeXml;
+ protected string BridgeXml {
+ get {
+ return _bridgeXml;
+ }
+ set {
+ _bridgeXml = value;
+ }
+ }
+
+ private BridgeService _bridgeService;
+ internal BridgeService BridgeService {
+ get {
+ // Only build the service once this way.
+ if (_bridgeService == null) {
+ // Try the cache first
+ _bridgeService = BridgeService.GetService(VirtualPath);
+ if (_bridgeService == null) {
+ _bridgeService = new BridgeService(BridgeXml);
+ BridgeService.UpdateCache(VirtualPath, _bridgeService);
+ }
+ }
+ return _bridgeService;
+ }
+ }
+
+ private string _virtualPath;
+ protected string VirtualPath {
+ get {
+ return _virtualPath;
+ }
+ set {
+ _virtualPath = value;
+ }
+ }
+
+ protected void BuildBridgeContext(string bridgePath, BridgeRequest request) {
+ _context = new BridgeContext(request, bridgePath);
+ }
+
+ private BridgeMethodInfo GetMethodInfoForCall(string method) {
+ BridgeMethodInfo methodInfo = null;
+ if (!BridgeService.ServiceInfo.Methods.TryGetValue(method, out methodInfo)) {
+ throw new ArgumentException("No such method registered: " + method);
+ }
+ return methodInfo;
+ }
+
+ // Shortest possible string that can contain an expression
+ private const int MinimumExpressionLength = 10;
+ private static char[] s_sep = { ':' };
+ internal static object TryParseExpression(string param, BridgeContext context) {
+ string exp = param;
+ if (param.Length > MinimumExpressionLength && param.StartsWith("%", StringComparison.Ordinal) && param.EndsWith("%", StringComparison.Ordinal)) {
+ exp = param.Substring(1, param.Length - 2).Trim();
+ }
+ else {
+ return param;
+ }
+
+ string[] pieces = exp.Split(s_sep);
+ if (pieces.Length > 1) {
+ switch (pieces[0].Trim()) {
+ case "args":
+ string key = pieces[1].Trim();
+ if (context != null && context.BridgeRequest.Args.Contains(key)) {
+ return context.BridgeRequest.Args[key];
+ }
+ else {
+ throw new ArgumentException("Failed to find object in Args: " + key + " for expression: " + param);
+ }
+ case "appsettings":
+ return WebConfigurationManager.AppSettings[pieces[1].Trim()];
+ case "resultschain":
+ if (context != null && pieces.Length == 3) {
+ ICollection results = context.ResultsChain[pieces[1].Trim()] as ICollection;
+ if (results == null || results.Count == 0)
+ throw new ArgumentException("Results expression only works for a non empty Collection of IDictionary: " + param);
+
+ IEnumerator iterator = results.GetEnumerator();
+ iterator.MoveNext();
+ IDictionary dict = iterator.Current as IDictionary;
+ if (dict == null)
+ throw new ArgumentException("Results expression only works for a List of IDictionary: " + param);
+ string propertyKey = pieces[2].Trim();
+ string result = dict[propertyKey] as string;
+ if (result != null) {
+ return result;
+ }
+ else {
+ throw new ArgumentException("Failed to parse expression: Could not find: " + propertyKey + " in results for: " + param);
+ }
+ }
+ break;
+ case "querystring":
+ return HttpContext.Current.Request.QueryString[pieces[1].Trim()];
+ default:
+ throw new ArgumentException("Unknown expression type: " + param);
+ }
+ }
+ throw new ArgumentException("Failed to parse expression, make sure its well formed: " + param);
+ }
+
+ // Helper function that resolve the config parameter values, client args, and expressions
+ private static void ResolveParameters(Dictionary<string, BridgeParameterInfo> parameterInfo, Dictionary<string, object> args, BridgeContext context) {
+ foreach (BridgeParameterInfo paramInfo in parameterInfo.Values) {
+ object paramValue = null;
+
+ // Fill in server side values as default always
+ if (paramInfo.Value != null) {
+ paramValue = paramInfo.Value;
+ }
+
+ // REVIEW: what happens if doesn't exist and no default, should probably throw here? or just use null (using null for now)
+ if (!paramInfo.ServerOnly) {
+ if (context.BridgeRequest.Args.Contains(paramInfo.Name)) {
+ paramValue = context.BridgeRequest.Args[paramInfo.Name];
+ }
+ }
+
+ // Handle expressions of form value= "% appsettings | querystring : key %"
+ string paramValueString = paramValue as string;
+ if (paramValueString != null) {
+ paramValue = TryParseExpression(paramValueString, context);
+ }
+
+ args[paramInfo.ServerName] = paramValue;
+ }
+ }
+
+ // This is the signature which we code gen the actual calls to the method
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "3#", Justification = "Consistency.")]
+ public virtual object CallServiceClassMethod(string method, Dictionary<string, object> args, ICredentials credentials, string url) {
+ return null;
+ }
+
+
+ // Used by the generated proxy methods to convert parameter types to the right type
+ protected static object ConvertToType(object argValue, Type parameterType) {
+ string name = Assembly.CreateQualifiedName(typeof(JavaScriptSerializer).Assembly.FullName, "System.Web.Script.Serialization.ObjectConverter");
+ Type conv = Type.GetType(name);
+ MethodInfo method = conv.GetMethod("ConvertObjectToType", BindingFlags.NonPublic | BindingFlags.Static);
+ return method.Invoke(null, new object[] { argValue, parameterType, new JavaScriptSerializer() });
+ }
+
+ public virtual void TransformRequest() {
+ BridgeMethodInfo methodInfo = GetMethodInfoForCall(BridgeRequest.Method);
+
+ // Set the server method name
+ ServiceRequest.Method = methodInfo.ServerName;
+
+ // Apply the parameter mapping/expressions
+ ResolveParameters(methodInfo.Parameters, ServiceRequest.Args, Context);
+
+ // Apply the credentials now only if the credentials aren't set already
+ BridgeCredentialInfo credInfo = methodInfo.Credentials;
+ if (ServiceRequest.Credentials == null && credInfo != null) {
+ ServiceRequest.Credentials = new NetworkCredential((string)TryParseExpression(credInfo.User, Context), (string)TryParseExpression(credInfo.Password, Context), (string)TryParseExpression(credInfo.Domain, Context));
+ }
+ }
+
+ // Hook to fullfill the request from the cache, return value of true stops execution of the bridge pipeline and returns what's in BridgeResponse.Response
+ public virtual bool ResolveRequestCache() {
+ BridgeMethodInfo methodInfo = GetMethodInfoForCall(BridgeRequest.Method);
+ // First cache that has a hit we use
+ foreach (IBridgeRequestCache cache in methodInfo.CacheInstances) {
+ object rawResponse = cache.Lookup(Context);
+ if (rawResponse != null) {
+ BridgeResponse.Response = rawResponse;
+ return true;
+ }
+ }
+ return false;
+ }
+ public virtual void ProcessRequest() {
+ // Resolve the url before we make the call
+ // If the ServiceUrl is specified on the BridgeRequest, use that instead
+ string url = BridgeRequest.ServiceUrl;
+ if (string.IsNullOrEmpty(url)) {
+ url = BridgeService.ServiceInfo.ServiceUrl;
+ }
+
+ // Now handle expressions
+ if (!string.IsNullOrEmpty(url)) {
+ url = BridgeHandler.TryParseExpression(url, Context) as string;
+ if (url == null) {
+ throw new ArgumentException("The expression for url must evaluate to a string object.");
+ }
+ }
+
+ // For now we special case the REST proxy
+ if (string.Equals(BridgeService.ServiceInfo.ServiceClass, "Microsoft.Web.Preview.Services.BridgeRestProxy")) {
+ ServiceResponse.Response = BridgeRestProxy.MakeRestCall(url, ServiceRequest.Args, ServiceRequest.Credentials);
+ }
+ else {
+ // This method gets code gen'ed to call the actual proxy method (see BridgeBuildProvider.cs)
+ ServiceResponse.Response = CallServiceClassMethod(ServiceRequest.Method, ServiceRequest.Args, ServiceRequest.Credentials, url);
+ }
+ }
+ public virtual void TransformResponse() {
+ object rawResponse = ServiceResponse.Response;
+ BridgeMethodInfo methodInfo = GetMethodInfoForCall(BridgeRequest.Method);
+ foreach (Pair pair in methodInfo.ResponseTransforms) {
+ Type type;
+ string typeStr = (string)pair.First;
+ IBridgeResponseTransformer transformer = BridgeService.CreateInstance(typeStr, out type) as IBridgeResponseTransformer;
+ if (transformer == null) {
+ throw new InvalidOperationException(typeStr + " is not of type IBridgeResponseTransformer");
+ }
+ transformer.Initialize((BridgeTransformData)pair.Second);
+ rawResponse = transformer.Transform(rawResponse);
+ }
+ BridgeResponse.Response = rawResponse;
+ }
+
+ // This is where the transformed response is placed into the cache
+ public virtual void UpdateResponseCache() {
+ BridgeMethodInfo methodInfo = GetMethodInfoForCall(BridgeRequest.Method);
+ // First cache that has a hit we use
+ foreach (IBridgeRequestCache cache in methodInfo.CacheInstances) {
+ cache.Put(Context);
+ }
+ }
+
+ // Entrypoint to the pipeline
+ protected virtual void ExecuteBridgePipeline() {
+ // Make the calls to all other bridge methods first
+ BridgeMethodInfo methodInfo = GetMethodInfoForCall(BridgeRequest.Method);
+ foreach (BridgeChainRequestInfo callInfo in methodInfo.BridgeChainRequests) {
+ Dictionary<string, object> args = new Dictionary<string, object>();
+ ResolveParameters(callInfo.Parameters, args, Context);
+ BridgeRequest request = new BridgeRequest(callInfo.Method, args);
+ object results = BridgeHandler.Invoke(callInfo.BridgeUrl, request);
+ Context.ResultsChain[callInfo.Name] = results;
+ }
+
+ TransformRequest();
+
+ // Stop execution if we have a cache hit
+ if (ResolveRequestCache()) return;
+
+ ProcessRequest();
+ TransformResponse();
+ UpdateResponseCache();
+ }
+
+ // Public invocation of the entry point
+ public object Invoke(BridgeRequest request) {
+ BuildBridgeContext(VirtualPath, request);
+ ExecuteBridgePipeline();
+ return BridgeResponse.Response;
+ }
+
+ // For bridge to bridge scenario, or invoking bridge statically
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification = "Consistency.")]
+ public static object Invoke(string bridgeUrl, BridgeRequest request) {
+ bridgeUrl = VirtualPathUtility.ToAbsolute(bridgeUrl);
+
+ Type type = BuildManager.GetCompiledType(bridgeUrl);
+ if (type == null || !typeof(BridgeHandler).IsAssignableFrom(type)) {
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, PreviewWeb.BridgeHandler_CannotLoad, bridgeUrl));
+ }
+ BridgeHandler bridge = Activator.CreateInstance(type) as BridgeHandler;
+ if (bridge == null) {
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, PreviewWeb.BridgeHandler_CannotCreate, bridgeUrl));
+ }
+ return bridge.Invoke(request);
+ }
+
+ }
+}
View
39 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeModule.cs
@@ -0,0 +1,39 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Web;
+ using System.Web.Hosting;
+
+ // Temporary module which we need to support access to asbx extensions for people unable to change IIS mappings
+ public sealed class BridgeModule : IHttpModule {
+ void IHttpModule.Init(HttpApplication context) {
+ if (context == null) {
+ throw new ArgumentNullException("context");
+ }
+ context.BeginRequest += new EventHandler(OnBeginRequestHandler);
+ }
+
+ void IHttpModule.Dispose() {
+ }
+
+ internal const string BridgeSuffix = "bridge.axd";
+ internal const int BridgeSuffixLength = 10;
+
+ void OnBeginRequestHandler(Object source, EventArgs eventArgs) {
+ HttpContext context = ((HttpApplication)source).Context;
+ string bridgePath = context.Request.FilePath;
+
+ // The paths we rewrite will be in the form of /atlas/BCL/MSNBridge.axd[/js] --> /atlas/BCL/MSN.asbx[/js]
+ if (bridgePath.EndsWith(BridgeSuffix, StringComparison.OrdinalIgnoreCase)) {
+ // Replace AtlasBridge.axd with .asbx and that's the real path
+ bridgePath = context.Request.Path.Substring(0, bridgePath.Length - BridgeSuffixLength) + ".asbx";
+
+ // Only rewrite the path if the bridge file exists
+ VirtualPathProvider pathProvider = HostingEnvironment.VirtualPathProvider;
+ if (pathProvider.FileExists(bridgePath)) {
+ context.RewritePath(bridgePath, context.Request.PathInfo, null);
+ }
+ }
+ }
+ }
+
+}
View
55 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeRequest.cs
@@ -0,0 +1,55 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections;
+
+ public class BridgeRequest {
+ private string _method;
+ public string Method {
+ get {
+ return _method;
+ }
+ set {
+ if (string.IsNullOrEmpty(value)) {
+ throw new ArgumentNullException("value");
+ }
+ _method = value;
+ }
+ }
+
+ private IDictionary _args;
+
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Unknown.")]
+ public IDictionary Args {
+ get {
+ return _args;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+ _args = value;
+ }
+ }
+
+ private string _serviceUrl;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Consistency.")]
+ public string ServiceUrl {
+ get {
+ return _serviceUrl;
+ }
+ set {
+ _serviceUrl = value;
+ }
+ }
+
+ public BridgeRequest(string method, IDictionary args) {
+ Method = method;
+
+ // REVIEW: Treat null args as empty dictionary, enables Get bridge requests currently
+ if (args == null) args = new Hashtable();
+ Args = args;
+ }
+ }
+}
View
15 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeResponse.cs
@@ -0,0 +1,15 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+
+ public class BridgeResponse {
+ private object _response;
+ public Object Response {
+ get {
+ return _response;
+ }
+ set {
+ _response = value;
+ }
+ }
+ }
+}
View
49 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeRestProxy.cs
@@ -0,0 +1,49 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections;
+ using System.IO;
+ using System.Net;
+ using System.Text;
+ using Microsoft.Web.Preview.Resources;
+
+ public static class BridgeRestProxy {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification = "Consistency.")]
+ public static string MakeRestCall(string url, IDictionary argsDictionary, ICredentials credentials) {
+ if (String.IsNullOrEmpty(url)) {
+ throw new ArgumentException(PreviewWeb.BridgeRestProxy_EmptyUrl, "url");
+ }
+
+ string requestUrl = BuildRestRequest(url, argsDictionary);
+ HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(new Uri(requestUrl));
+ webRequest.Proxy = WebRequest.GetSystemWebProxy();
+ if (credentials != null)
+ webRequest.Credentials = credentials;
+ HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
+ Stream stream = response.GetResponseStream();
+ using (TextReader reader = new StreamReader(stream)) {
+ return reader.ReadToEnd();
+ }
+ }
+
+ private static string BuildRestRequest(string url, IDictionary args) {
+ StringBuilder request = new StringBuilder(url);
+ if (args != null && args.Count > 0) {
+ bool first = true;
+ foreach (string key in args.Keys) {
+ if (first) {
+ request.Append('?');
+ first = false;
+ }
+ else {
+ request.Append('&');
+ }
+ // REVIEW: Do we need to url encode these guys?
+ request.Append(key);
+ request.Append('=');
+ request.Append(args[key]);
+ }
+ }
+ return request.ToString();
+ }
+ }
+}
View
605 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/BridgeService.cs
@@ -0,0 +1,605 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Web.Compilation;
+ using System.Web.Script.Services;
+ using System.Web.UI;
+ using System.Xml;
+ using Microsoft.Web.Preview.Resources;
+
+ internal class BridgeService {
+ private static Dictionary<string, BridgeService> s_cache = new Dictionary<string, BridgeService>();
+ public static BridgeService GetService(string virtualPath) {
+ BridgeService service = null;
+ if (s_cache.TryGetValue(virtualPath, out service)) {
+ return service;
+ }
+ return null;
+ }
+ public static void UpdateCache(string virtualPath, BridgeService service) {
+ lock (s_cache) {
+ s_cache[virtualPath] = service;
+ }
+ }
+
+ private string _namespace;
+ public String Namespace {
+ get {
+ return _namespace;
+ }
+ set {
+ _namespace = value;
+ }
+ }
+
+ private string _className;
+ public String Classname {
+ get {
+ return _className;
+ }
+ set {
+ _className = value;
+ }
+ }
+
+ private string _language;
+ public String Language {
+ get {
+ return _language;
+ }
+ set {
+ _language = value;
+ }
+ }
+
+ private string _partialClassFile;
+ public String PartialClassFile {
+ get {
+ return _partialClassFile;
+ }
+ set {
+ _partialClassFile = value;
+ }
+ }
+
+ private ServiceInfo _serviceInfo;
+ public ServiceInfo ServiceInfo {
+ get {
+ return _serviceInfo;
+ }
+ set {
+ _serviceInfo = value;
+ }
+ }
+
+ public BridgeService(string xml) {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(xml);
+ Initialize(doc);
+ }
+
+ private void Initialize(XmlDocument document) {
+ XmlNode rootNode = document.SelectSingleNode("/bridge");
+ if (rootNode == null)
+ throw new InvalidOperationException("No <bridge> node found");
+
+ Namespace = GetAttributeValue(rootNode, "namespace", true);
+ Classname = GetAttributeValue(rootNode, "className", true);
+ PartialClassFile = GetAttributeValue(rootNode, "partialClassFile", false);
+ Language = GetAttributeValue(rootNode, "language", false);
+ if (String.IsNullOrEmpty(Language)) {
+ Language = "C#";
+ }
+
+ ServiceInfo = BuildServiceInfo(rootNode);
+ }
+
+ private static string GetAttributeValue(XmlNode node, string attr, bool required) {
+ XmlAttribute attrib = node.Attributes[attr];
+ if (attrib == null) {
+ if (required) {
+ throw new InvalidOperationException("Attribute: " + attr + " is required.");
+ }
+ else {
+ return null;
+ }
+ }
+ return attrib.Value;
+ }
+
+ private static Dictionary<string, BridgeParameterInfo> BuildParams(XmlNode methodNode) {
+ XmlNodeList paramNodes = methodNode.SelectNodes("parameter");
+ Dictionary<string, BridgeParameterInfo> parameters = new Dictionary<string, BridgeParameterInfo>(paramNodes.Count);
+ foreach (XmlNode paramNode in paramNodes) {
+ BridgeParameterInfo param = new BridgeParameterInfo();
+ param.Name = GetAttributeValue(paramNode, "name", true);
+ param.Value = GetAttributeValue(paramNode, "value", false);
+ param.ServerName = GetAttributeValue(paramNode, "serverName", false);
+ string serverOnly = GetAttributeValue(paramNode, "serverOnly", false);
+ param.ServerOnly = (serverOnly != null && string.Equals(serverOnly, "true", StringComparison.OrdinalIgnoreCase));
+ parameters.Add(param.Name, param);
+ }
+ return parameters;
+ }
+
+ /*
+ <data>
+ <attribute name="selector" value="bs:Items/bs:Item" />
+ <dictionary name="namespaceMapping">
+ <item name="bs" value="http://webservices.amazon.com/AWSECommerceService/2005-10-05" />
+ </dictionary>
+ <dictionary name="selectedNodes">
+ <item name="Title" value="bs:ItemAttributes/bs:Title" />
+ <item name="Product" value="bs:ItemAttributes/bs:ProductGroup" />
+ <item name="Author" value="bs:ItemAttributes/bs:Author" />
+ <item name="ASIN" value="bs:ASIN" />
+ </dictionary>
+ </data>
+ */
+ private static BridgeTransformData BuildTransformData(XmlNode dataNode) {
+ BridgeTransformData data = new BridgeTransformData();
+ if (dataNode != null) {
+ XmlNodeList attrNodes = dataNode.SelectNodes("attribute");
+ foreach (XmlNode node in attrNodes) {
+ string key = GetAttributeValue(node, "name", true);
+ string value = GetAttributeValue(node, "value", true);
+ data.Attributes[key] = value;
+ }
+
+ XmlNodeList dictNodes = dataNode.SelectNodes("dictionary");
+ foreach (XmlNode dictNode in dictNodes) {
+ string name = GetAttributeValue(dictNode, "name", true);
+ XmlNodeList items = dictNode.SelectNodes("item");
+ Dictionary<string, string> d = new Dictionary<string, string>(items.Count);
+
+ foreach (XmlNode itemNode in items) {
+ string key = GetAttributeValue(itemNode, "name", true);
+ string value = GetAttributeValue(itemNode, "value", true);
+ d[key] = value;
+ }
+ data.Dictionaries[name] = d;
+ }
+
+ }
+ return data;
+ }
+
+ private static void BuildTransforms(XmlNode transformNode, BridgeMethodInfo method) {
+ if (transformNode == null) return;
+ XmlNodeList transformNodes = transformNode.SelectNodes("transform");
+ foreach (XmlNode node in transformNodes) {
+ string typeStr = GetAttributeValue(node, "type", true);
+ XmlNode dataNode = GetSingleNode(node, "data", false);
+ BridgeTransformData data = BuildTransformData(dataNode);
+ method.ResponseTransforms.Add(new Pair(typeStr, data));
+ }
+ }
+
+ private static void BuildCaches(XmlNode cacheNode, BridgeMethodInfo method) {
+ if (cacheNode == null) return;
+ XmlNodeList cacheNodes = cacheNode.SelectNodes("cache");
+ foreach (XmlNode node in cacheNodes) {
+ string typeStr = GetAttributeValue(node, "type", true);
+ XmlNode dataNode = GetSingleNode(node, "data", false);
+ BridgeTransformData data = BuildTransformData(dataNode);
+ method.Caches.Add(new Pair(typeStr, data));
+ }
+ }
+ private static void BuildMethodRequestChain(XmlNode callNode, BridgeMethodInfo method) {
+ XmlNodeList requests = callNode.SelectNodes("request");
+ foreach (XmlNode node in requests) {
+ BridgeChainRequestInfo callInfo = new BridgeChainRequestInfo();
+ callInfo.Name = GetAttributeValue(node, "name", true);
+ callInfo.BridgeUrl = GetAttributeValue(node, "bridgeUrl", true);
+ callInfo.Method = GetAttributeValue(node, "method", true);
+ method.BridgeChainRequests.Add(callInfo);
+
+ XmlNode inputNode = GetSingleNode(node, "input", false);
+ if (inputNode == null) {
+ callInfo.Parameters = new Dictionary<string, BridgeParameterInfo>(0);
+ }
+ else {
+ callInfo.Parameters = BuildParams(inputNode);
+ }
+
+ }
+ }
+
+ private static BridgeCredentialInfo ParseCredentials(XmlNode authNode) {
+ BridgeCredentialInfo cred = null;
+ XmlNode credNode = authNode.SelectSingleNode("credentials");
+ if (credNode != null) {
+ cred = new BridgeCredentialInfo();
+ cred.User = GetAttributeValue(credNode, "username", true);
+ cred.Password = GetAttributeValue(credNode, "password", true);
+ cred.Domain = GetAttributeValue(credNode, "domain", true);
+ }
+ return cred;
+ }
+
+ private static XmlNode GetSingleNode(XmlNode node, string name, bool required) {
+ XmlNode childNode = node.SelectSingleNode(name);
+ if (required && childNode == null) {
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, PreviewWeb.BridgeService_NodeRequired, name));
+ }
+ return childNode;
+ }
+ private static XmlNode GetSingleNode(XmlNode node, string name) {
+ return GetSingleNode(node, name, true);
+ }
+
+ private static void BuildMethodInfo(ServiceInfo serviceInfo, XmlNode node) {
+ XmlNodeList methodNodes = node.SelectNodes("method");
+ foreach (XmlNode methodNode in methodNodes) {
+ string name = GetAttributeValue(methodNode, "name", true);
+ string serverName = GetAttributeValue(methodNode, "serverName", false);
+ if (serverName == null) serverName = name;
+
+ string getEnabled = GetAttributeValue(methodNode, "getEnabled", false);
+ bool get = (getEnabled != null && String.Equals(getEnabled, "true", StringComparison.OrdinalIgnoreCase));
+
+ ResponseFormat mode = ResponseFormat.Json;
+ string responseFormat = GetAttributeValue(methodNode, "responseFormat", false);
+ if (responseFormat != null && String.Equals(responseFormat, "xml", StringComparison.OrdinalIgnoreCase)) {
+ mode = ResponseFormat.Xml;
+ }
+
+ BridgeMethodInfo methodInfo = new BridgeMethodInfo(name, serverName, get, mode);
+ XmlNode inputNode = GetSingleNode(methodNode, "input", false);
+ if (inputNode == null) {
+ methodInfo.Parameters = new Dictionary<string, BridgeParameterInfo>(0);
+ }
+ else {
+ methodInfo.Parameters = BuildParams(inputNode);
+ }
+
+ XmlNode requests = GetSingleNode(methodNode, "requestChain", false);
+ if (requests != null) {
+ BuildMethodRequestChain(requests, methodInfo);
+ }
+
+ // REVIEW: Only used on Soap stuff currently
+ XmlNodeList includeNodes = methodNode.SelectNodes("xmlinclude");
+ foreach (XmlNode includeNode in includeNodes) {
+ methodInfo.XmlIncludes.Add(GetAttributeValue(includeNode, "type", true));
+ }
+
+ XmlNode transformNode = GetSingleNode(methodNode, "transforms", false);
+ BuildTransforms(transformNode, methodInfo);
+
+ XmlNode cachingNode = GetSingleNode(methodNode, "caching", false);
+ BuildCaches(cachingNode, methodInfo);
+
+ XmlNode authNode = methodNode.SelectSingleNode("authentication");
+ if (authNode != null) {
+ methodInfo.Credentials = ParseCredentials(authNode);
+ }
+
+ serviceInfo.Methods[name] = methodInfo;
+ }
+ }
+
+ private static ServiceInfo BuildServiceInfo(XmlNode node) {
+ ServiceInfo serviceInfo = new ServiceInfo();
+ XmlNode proxyNode = GetSingleNode(node, "proxy");
+ serviceInfo.ServiceClass = GetAttributeValue(proxyNode, "type", true);
+ serviceInfo.ServiceUrl = GetAttributeValue(proxyNode, "serviceUrl", false);
+ BuildMethodInfo(serviceInfo, node);
+ return serviceInfo;
+ }
+
+ // Cache the types once, but create a new instance each invocation
+ private static Dictionary<string, Type> s_typeCache = new Dictionary<string, Type>();
+ internal static Type GetType(string type) {
+ Type serviceType;
+ if (!s_typeCache.TryGetValue(type, out serviceType)) {
+ serviceType = BuildManager.GetType(type, true);
+ if (serviceType == null) {
+ throw new ArgumentException("cannot find Type: " + type);
+ }
+ s_typeCache[type] = serviceType;
+ }
+ return serviceType;
+ }
+ internal static object CreateInstance(string type, out Type serviceType) {
+ serviceType = GetType(type);
+ object serviceObject = Activator.CreateInstance(serviceType);
+ if (serviceObject == null) {
+ throw new ArgumentException("cannot instantiate Type: " + type);
+ }
+ return serviceObject;
+ }
+ }
+
+ internal class ServiceInfo {
+ private Dictionary<string, BridgeMethodInfo> _methods = new Dictionary<string, BridgeMethodInfo>();
+ public Dictionary<string, BridgeMethodInfo> Methods {
+ get {
+ return _methods;
+ }
+ }
+
+ private string _url;
+ public string ServiceUrl {
+ get {
+ return _url;
+ }
+ set {
+ _url = value;
+ }
+ }
+
+
+ // REVIEW: Rename this proxy?
+ private string _serviceClass;
+ public string ServiceClass {
+ get {
+ return _serviceClass;
+ }
+ set {
+ _serviceClass = value;
+ }
+ }
+
+ public ServiceInfo() {
+ }
+ }
+
+ internal class BridgeMethodInfo {
+ public BridgeMethodInfo(string name, string serverName, bool getEnabled, ResponseFormat responseFormat) {
+ Name = name;
+ ServerName = serverName;
+ GetEnabled = getEnabled;
+ ResponseFormat = responseFormat;
+ }
+
+ private BridgeCredentialInfo _creds;
+ public BridgeCredentialInfo Credentials {
+ get {
+ return _creds;
+ }
+ set {
+ _creds = value;
+ }
+ }
+
+ private string _name;
+ public string Name {
+ get {
+ return _name;
+ }
+ set {
+ _name = value;
+ }
+ }
+
+ private string _serverName;
+ public string ServerName {
+ get {
+ return _serverName;
+ }
+ set {
+ _serverName = value;
+ }
+ }
+
+ private bool _getEnabled;
+ public bool GetEnabled {
+ get {
+ return _getEnabled;
+ }
+ set {
+ _getEnabled = value;
+ }
+ }
+
+ private ResponseFormat _responseFormat;
+ public ResponseFormat ResponseFormat {
+ get {
+ return _responseFormat;
+ }
+ set {
+ _responseFormat = value;
+ }
+ }
+
+ private Dictionary<string, BridgeParameterInfo> _parameters;
+ public Dictionary<string, BridgeParameterInfo> Parameters {
+ get {
+ return _parameters;
+ }
+ set {
+ _parameters = value;
+ }
+ }
+
+ private List<string> _xmlIncludes = new List<string>();
+ public List<string> XmlIncludes {
+ get {
+ return _xmlIncludes;
+ }
+ }
+
+ private List<BridgeChainRequestInfo> _requests = new List<BridgeChainRequestInfo>();
+ public List<BridgeChainRequestInfo> BridgeChainRequests {
+ get {
+ return _requests;
+ }
+ }
+
+ private List<Pair> _responseTransforms = new List<Pair>();
+ public List<Pair> ResponseTransforms {
+ get {
+ return _responseTransforms;
+ }
+ }
+
+ private List<Pair> _caches = new List<Pair>();
+ public List<Pair> Caches {
+ get {
+ return _caches;
+ }
+ }
+
+ private List<IBridgeRequestCache> _cacheInstances;
+ public List<IBridgeRequestCache> CacheInstances {
+ get {
+ if (_cacheInstances == null) {
+ _cacheInstances = new List<IBridgeRequestCache>(Caches.Count);
+ foreach (Pair pair in Caches) {
+ Type type;
+ string typeStr = (string)pair.First;
+ IBridgeRequestCache cache = BridgeService.CreateInstance(typeStr, out type) as IBridgeRequestCache;
+ if (cache == null) {
+ throw new InvalidOperationException(typeStr + " is not of type IBridgeRequestCache");
+ }
+ cache.Initialize((BridgeTransformData)pair.Second);
+ _cacheInstances.Add(cache);
+ }
+
+ }
+ return _cacheInstances;
+ }
+ }
+
+ }
+
+ internal class BridgeCredentialInfo {
+ private string _user;
+ public string User {
+ get {
+ return _user;
+ }
+ set {
+ _user = value;
+ }
+ }
+
+ private string _domain;
+ public string Domain {
+ get {
+ return _domain;
+ }
+ set {
+ _domain = value;
+ }
+ }
+
+ private string _password;
+ public string Password {
+ get {
+ return _password;
+ }
+ set {
+ _password = value;
+ }
+ }
+ }
+
+ internal class BridgeChainRequestInfo {
+ private string _name;
+ public string Name {
+ get {
+ return _name;
+ }
+ set {
+ _name = value;
+ }
+ }
+
+ private string _bridgeUrl;
+ public string BridgeUrl {
+ get {
+ return _bridgeUrl;
+ }
+ set {
+ _bridgeUrl = value;
+ }
+ }
+
+ private string _method;
+ public string Method {
+ get {
+ return _method;
+ }
+ set {
+ _method = value;
+ }
+ }
+
+ private Dictionary<string, BridgeParameterInfo> _parameters;
+ public Dictionary<string, BridgeParameterInfo> Parameters {
+ get {
+ return _parameters;
+ }
+ set {
+ _parameters = value;
+ }
+ }
+ }
+
+ internal class BridgeParameterInfo {
+ private string _name;
+ public string Name {
+ get {
+ return _name;
+ }
+ set {
+ _name = value;
+ }
+ }
+
+ private string _serverName;
+ public string ServerName {
+ get {
+ if (_serverName == null)
+ return Name;
+ return _serverName;
+ }
+ set {
+ _serverName = value;
+ }
+ }
+
+ private string _value;
+ public string Value {
+ get {
+ return _value;
+ }
+ set {
+ _value = value;
+ }
+ }
+
+ private bool _serverOnly;
+ public bool ServerOnly {
+ get {
+ return _serverOnly;
+ }
+ set {
+ _serverOnly = value;
+ }
+ }
+ }
+
+ // shared with IBridgeRequestCache
+ public class BridgeTransformData {
+ private Dictionary<string, Dictionary<string, string>> _dictionaries = new Dictionary<string, Dictionary<string, string>>();
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
+ Justification = "Fixing this would require new types and new OM.")]
+ public Dictionary<string, Dictionary<string, string>> Dictionaries {
+ get {
+ return _dictionaries;
+ }
+ }
+
+ private Dictionary<string, string> _attributes = new Dictionary<string, string>();
+ public Dictionary<string, string> Attributes {
+ get {
+ return _attributes;
+ }
+ }
+ }
+}
View
12 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/IBridgeRequestCache.cs
@@ -0,0 +1,12 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ public interface IBridgeRequestCache {
+ void Initialize(BridgeTransformData data);
+ object Lookup(BridgeContext context);
+ void Put(BridgeContext context);
+ void Clear();
+ }
+}
View
6 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/IBridgeResponseTransformer.cs
@@ -0,0 +1,6 @@
+namespace Microsoft.Web.Preview.Services {
+ public interface IBridgeResponseTransformer {
+ void Initialize(BridgeTransformData data);
+ object Transform(object results);
+ }
+}
View
50 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/ObjectMapperBridgeTransformer.cs
@@ -0,0 +1,50 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.IO;
+ using System.Collections;
+
+ public class ObjectMapperBridgeTransformer : IBridgeResponseTransformer {
+ private string _selector;
+ private Dictionary<string, string> _propertyMap;
+
+ public void Initialize(BridgeTransformData data) {
+ if (!data.Dictionaries.TryGetValue("propertyMap", out _propertyMap)) {
+ throw new ArgumentException("ObjectMapperBridgeTransformer requires a selectedNodes dictionary");
+ }
+ if (!data.Attributes.TryGetValue("selector", out _selector)) {
+ throw new ArgumentException("ObjectMapperBridgeTransformer requires a selector attribute");
+ }
+ }
+
+ public object Transform(object results) {
+ // REVIEW: Probably should rethrow exceptions with different text
+ IEnumerable objects = null;
+ if (_selector == "this") {
+ objects = results as IEnumerable;
+ if (objects == null) {
+ List<object> l = new List<object>();
+ l.Add(results);
+ objects = l;
+ }
+ }
+ else {
+ objects = System.Web.UI.DataBinder.Eval(results, _selector) as IEnumerable;
+ if (objects == null) {
+ throw new InvalidOperationException("ObjectMapperBridgeTransformer: selector property must contain an IEnumerable");
+ }
+ }
+
+ List<Dictionary<string, object>> returnValue = new List<Dictionary<string, object>>();
+ foreach (object obj in objects) {
+ Dictionary<string, object> shreddedObj = new Dictionary<string, object>();
+ foreach (string key in _propertyMap.Keys) {
+ shreddedObj[key] = System.Web.UI.DataBinder.Eval(obj, _propertyMap[key]);
+ }
+ returnValue.Add(shreddedObj);
+ }
+ return returnValue;
+ }
+ }
+}
View
34 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/ServiceRequest.cs
@@ -0,0 +1,34 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+ using System.Net;
+
+ public class ServiceRequest {
+ Dictionary<string, object> _args = new Dictionary<string, object>();
+ public Dictionary<string, object> Args {
+ get {
+ return _args;
+ }
+ }
+
+ private ICredentials _creds;
+ public ICredentials Credentials {
+ get {
+ return _creds;
+ }
+ set {
+ _creds = value;
+ }
+ }
+
+ private string _method;
+ public string Method {
+ get {
+ return _method;
+ }
+ set {
+ _method = value;
+ }
+ }
+ }
+}
View
17 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/ServiceResponse.cs
@@ -0,0 +1,17 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ public class ServiceResponse {
+ private object _response;
+ public Object Response {
+ get {
+ return _response;
+ }
+ set {
+ _response = value;
+ }
+ }
+ }
+}
View
57 AJAX/Futures/July 2007 Futures/AtlasBridgePublic/Services/XPathBridgeTransformer.cs
@@ -0,0 +1,57 @@
+namespace Microsoft.Web.Preview.Services {
+ using System;
+ using System.Collections.Generic;
+ using System.Xml;
+ using Microsoft.Web.Preview.Resources;
+
+ public class XPathBridgeTransformer : IBridgeResponseTransformer {
+ private Dictionary<string, string> _namespaceMapping;
+ private string _selector;
+ private Dictionary<string, string> _selectedNodeMap;
+
+ public void Initialize(BridgeTransformData data) {
+ if (!data.Dictionaries.TryGetValue("namespaceMapping", out _namespaceMapping)) {
+ _namespaceMapping = new Dictionary<string, string>();
+ }
+ if (!data.Dictionaries.TryGetValue("selectedNodes", out _selectedNodeMap)) {
+ throw new ArgumentException(PreviewWeb.XPathBridgeTransformer_RequiresSelectNodes, "data");
+ }
+ if (!data.Attributes.TryGetValue("selector", out _selector)) {
+ throw new ArgumentException(PreviewWeb.XPathBridgeTransformer_RequiresSelectorAttribute, "data");
+ }
+ }
+
+ private object BuildOutputStructure(XmlDocument xmlDocument) {
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
+
+ foreach (string ns in _namespaceMapping.Keys) {
+ nsmgr.AddNamespace(ns, (string)_namespaceMapping[ns]);
+ }
+
+ XmlNodeList resultNodes = xmlDocument.DocumentElement.SelectNodes(_selector, nsmgr);
+ List<Dictionary<string, string>> data = new List<Dictionary<string, string>>(resultNodes.Count);
+
+ foreach (XmlNode node in resultNodes) {
+ Dictionary<string, string> item = new Dictionary<string, string>();
+ foreach (string key in _selectedNodeMap.Keys) {
+ XmlNode leafNode = node.SelectSingleNode(_selectedNodeMap[key], nsmgr);
+ if (leafNode != null) {
+ item[key] = leafNode.InnerText;
+ }
+ }
+ data.Add(item);
+ }
+
+ return data;
+ }
+ public object Transform(object results) {
+ string xml = results as string;
+ if (xml == null) {
+ throw new ArgumentException(PreviewWeb.XPathBridgeTransformer_StringOnly, "results");
+ }
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.LoadXml(xml);
+ return BuildOutputStructure(xmlDocument);
+ }