[mapguide-commits] r5431 - in sandbox/maestro-3.0: MaestroAPITests OSGeo.MapGuide.MaestroAPI OSGeo.MapGuide.MaestroAPI/Commands OSGeo.MapGuide.MaestroAPI/Mapping OSGeo.MapGuide.MaestroAPI/Services OSGeo.MapGuide.MaestroAPI.Http OSGeo.MapGuide.MaestroAPI.Http/Commands OSGeo.MapGuide.MaestroAPI.Native OSGeo.MapGuide.MaestroAPI.Native/Commands

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Dec 2 04:59:15 EST 2010


Author: jng
Date: 2010-12-02 01:59:15 -0800 (Thu, 02 Dec 2010)
New Revision: 5431

Added:
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/Commands/
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/Commands/HttpGetResourceContents.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/Commands/LocalGetResourceContents.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/IGetResourceContents.cs
Modified:
   sandbox/maestro-3.0/MaestroAPITests/HttpConnectionTests.cs
   sandbox/maestro-3.0/MaestroAPITests/RuntimeMapTests.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeCapabilities.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/OSGeo.MapGuide.MaestroAPI.Native.csproj
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/CommandType.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs
Log:
This submission includes the following changes:
 - Include a IGetResourceContents custom command 
   - Provide a HTTP implementation (using ThreadPool)
   - Provide a Local implementation (using the MgResourceService.GetResourceContents() API introduced in 2.2). Consequently this command is disabled if connecting to a pre-2.2 MapGuide Server
 - Fix the cause of Rendering problems in RuntimeMap. I had a statement that set the MetersPerUnit back to 1.0 after setting our custom value! Yes. Very smart!
 - Reintroduce the RenderDynamicOverlay API
 - Add convenience Render methods to RuntimeMap
 - Update unit tests to test normal and convenience render methods
 - Update RuntimeMap to use batching via IGetResourceContents to pre-cache all required layer definitions if available. Unit tests indicate performance gains range from around 200% for HTTP and 300% for Local connections (as expected when using the GetResourceContents() API introduced in MG 2.2)

Modified: sandbox/maestro-3.0/MaestroAPITests/HttpConnectionTests.cs
===================================================================
--- sandbox/maestro-3.0/MaestroAPITests/HttpConnectionTests.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/MaestroAPITests/HttpConnectionTests.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -61,24 +61,24 @@
 
             Assert.IsNotNull(props);
             Assert.AreEqual(props.Length, 2);
-            Assert.IsTrue(Array.IndexOf<string>(props, "UserAgent") >= 0);
-            Assert.IsTrue(Array.IndexOf<string>(props, "BaseUrl") >= 0);
+            Assert.IsTrue(Array.IndexOf<string>(props, HttpServerConnection.PROP_USER_AGENT) >= 0);
+            Assert.IsTrue(Array.IndexOf<string>(props, HttpServerConnection.PROP_BASE_URL) >= 0);
 
             //It is of type string
-            var type = isvc.GetCustomPropertyType("UserAgent");
+            var type = isvc.GetCustomPropertyType(HttpServerConnection.PROP_USER_AGENT);
             Assert.AreEqual(type, typeof(string));
-            type = isvc.GetCustomPropertyType("BaseUrl");
+            type = isvc.GetCustomPropertyType(HttpServerConnection.PROP_BASE_URL);
             Assert.AreEqual(type, typeof(string));
 
             //We can set and get it
-            isvc.SetCustomProperty("UserAgent", "MapGuide Maestro API Unit Test Fixture");
-            var agent = (string)isvc.GetCustomProperty("UserAgent");
+            isvc.SetCustomProperty(HttpServerConnection.PROP_USER_AGENT, "MapGuide Maestro API Unit Test Fixture");
+            var agent = (string)isvc.GetCustomProperty(HttpServerConnection.PROP_USER_AGENT);
             Assert.AreEqual(agent, "MapGuide Maestro API Unit Test Fixture");
 
             //BaseUrl is read-only
             try
             {
-                isvc.SetCustomProperty("BaseUrl", "http://mylocalhost/mapguide");
+                isvc.SetCustomProperty(HttpServerConnection.PROP_BASE_URL, "http://mylocalhost/mapguide");
                 Assert.Fail("Should've thrown exception");
             }
             catch { } 

Modified: sandbox/maestro-3.0/MaestroAPITests/RuntimeMapTests.cs
===================================================================
--- sandbox/maestro-3.0/MaestroAPITests/RuntimeMapTests.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/MaestroAPITests/RuntimeMapTests.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -323,11 +323,46 @@
             map.Save();
 
             //Render default
-            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, "PNG"))
+            RenderAndVerify(mapSvc, map, "TestRender75k.png", "PNG");
+            RenderAndVerifyConvenience(map, "TestRender75kConvenience.png", "PNG");
+            RenderDynamicOverlayAndVerify(mapSvc, map, "TestRenderOverlay75k.png", "PNG");
+            RenderDynamicOverlayAndVerifyConvenience(map, "TestRenderOverlay75kConvenience.png", "PNG");
+
+            //Turn off parcels
+            var rail = map.GetLayerByName("Rail");
+            Assert.NotNull(rail);
+            rail.Visible = false;
+            map.Save();
+
+            //Render again
+            RenderAndVerify(mapSvc, map, "TestRender75k_NoRail.png", "PNG");
+            RenderAndVerifyConvenience(map, "TestRender75kConvenience_NoRail.png", "PNG");
+            RenderDynamicOverlayAndVerify(mapSvc, map, "TestRenderOverlay75k_NoRail.png", "PNG");
+            RenderDynamicOverlayAndVerifyConvenience(map, "TestRenderOverlay75kConvenience_NoRail.png", "PNG");
+
+            //Turn Rail back on
+            rail = null;
+            rail = map.GetLayerByName("Rail");
+            Assert.NotNull(rail);
+            rail.Visible = true;
+            map.Save();
+
+            //Render again
+            RenderAndVerify(mapSvc, map, "TestRender75k_RailBackOn.png", "PNG");
+            RenderAndVerifyConvenience(map, "TestRender75kConvenience_RailBackOn.png", "PNG");
+            RenderDynamicOverlayAndVerify(mapSvc, map, "TestRenderOverlay75k_RailBackOn.png", "PNG");
+            RenderDynamicOverlayAndVerifyConvenience(map, "TestRenderOverlay75kConvenience_RailBackOn.png", "PNG");
+        }
+
+        #region render helpers
+
+        private static void RenderDynamicOverlayAndVerifyConvenience(RuntimeMap map, string fileName, string format)
+        {
+            using (var stream = map.RenderDynamicOverlay(format, true))
             {
                 using (var ms = new MemoryStream())
                 using (var ms2 = new MemoryStream())
-                using (var fs = new FileStream("TestRender75k.png", FileMode.OpenOrCreate))
+                using (var fs = new FileStream(fileName, FileMode.OpenOrCreate))
                 {
                     Utility.CopyStream(stream, ms);
                     Utility.CopyStream(ms, ms2);
@@ -344,19 +379,40 @@
                     }
                 }
             }
+        }
 
-            //Turn off parcels
-            var rail = map.GetLayerByName("Rail");
-            Assert.NotNull(rail);
-            rail.Visible = false;
-            map.Save();
+        private static void RenderDynamicOverlayAndVerify(IMappingService mapSvc, RuntimeMap map, string fileName, string format)
+        {
+            using (var stream = mapSvc.RenderDynamicOverlay(map, map.Selection, format))
+            {
+                using (var ms = new MemoryStream())
+                using (var ms2 = new MemoryStream())
+                using (var fs = new FileStream(fileName, FileMode.OpenOrCreate))
+                {
+                    Utility.CopyStream(stream, ms);
+                    Utility.CopyStream(ms, ms2);
+                    Utility.CopyStream(ms, fs);
+                    //See if System.Drawing.Image accepts this
+                    try
+                    {
+                        using (var img = System.Drawing.Image.FromStream(ms))
+                        { }
+                    }
+                    catch (Exception ex)
+                    {
+                        Assert.Fail(ex.Message);
+                    }
+                }
+            }
+        }
 
-            //Render again
-            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, "PNG"))
+        private static void RenderAndVerify(IMappingService mapSvc, RuntimeMap map, string fileName, string format)
+        {
+            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, format))
             {
                 using (var ms = new MemoryStream())
                 using (var ms2 = new MemoryStream())
-                using (var fs = new FileStream("TestRender75k_NoRail.png", FileMode.OpenOrCreate))
+                using (var fs = new FileStream(fileName, FileMode.OpenOrCreate))
                 {
                     Utility.CopyStream(stream, ms);
                     Utility.CopyStream(ms, ms2);
@@ -373,20 +429,15 @@
                     }
                 }
             }
+        }
 
-            //Turn Rail back on
-            rail = null;
-            rail = map.GetLayerByName("Rail");
-            Assert.NotNull(rail);
-            rail.Visible = true;
-            map.Save();
-
-            //Render again
-            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, "PNG"))
+        private static void RenderAndVerifyConvenience(RuntimeMap map, string fileName, string format)
+        {
+            using (var stream = map.Render(format))
             {
                 using (var ms = new MemoryStream())
                 using (var ms2 = new MemoryStream())
-                using (var fs = new FileStream("TestRender75k_RailBackOn.png", FileMode.OpenOrCreate))
+                using (var fs = new FileStream(fileName, FileMode.OpenOrCreate))
                 {
                     Utility.CopyStream(stream, ms);
                     Utility.CopyStream(ms, ms2);
@@ -405,6 +456,8 @@
             }
         }
 
+        #endregion
+
         public virtual void TestRender12k()
         { 
             //Render a map of sheboygan at 12k
@@ -438,27 +491,10 @@
             map.Save();
 
             //Render default
-            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, "PNG"))
-            {
-                using (var ms = new MemoryStream())
-                using (var ms2 = new MemoryStream())
-                using (var fs = new FileStream("TestRender12k.png", FileMode.OpenOrCreate))
-                {
-                    Utility.CopyStream(stream, ms);
-                    Utility.CopyStream(ms, ms2);
-                    Utility.CopyStream(ms, fs);
-                    //See if System.Drawing.Image accepts this
-                    try
-                    {
-                        using (var img = System.Drawing.Image.FromStream(ms))
-                        { }
-                    }
-                    catch (Exception ex)
-                    {
-                        Assert.Fail(ex.Message);
-                    }
-                }
-            }
+            RenderAndVerify(mapSvc, map, "TestRender12k.png", "PNG");
+            RenderAndVerifyConvenience(map, "TestRender12kConvenience.png", "PNG");
+            RenderDynamicOverlayAndVerify(mapSvc, map, "TestRenderOverlay12k.png", "PNG");
+            RenderDynamicOverlayAndVerifyConvenience(map, "TestRenderOverlay12kConvenience.png", "PNG");
 
             //Turn off parcels
             var parcels = map.GetLayerByName("Parcels");
@@ -467,27 +503,10 @@
             map.Save();
             
             //Render again
-            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, "PNG"))
-            {
-                using (var ms = new MemoryStream())
-                using (var ms2 = new MemoryStream())
-                using (var fs = new FileStream("TestRender12k_NoParcels.png", FileMode.OpenOrCreate))
-                {
-                    Utility.CopyStream(stream, ms);
-                    Utility.CopyStream(ms, ms2);
-                    Utility.CopyStream(ms, fs);
-                    //See if System.Drawing.Image accepts this
-                    try
-                    {
-                        using (var img = System.Drawing.Image.FromStream(ms))
-                        { }
-                    }
-                    catch (Exception ex)
-                    {
-                        Assert.Fail(ex.Message);
-                    }
-                }
-            }
+            RenderAndVerify(mapSvc, map, "TestRender12k_NoParcels.png", "PNG");
+            RenderAndVerifyConvenience(map, "TestRender12kConvenience_NoParcels.png", "PNG");
+            RenderDynamicOverlayAndVerify(mapSvc, map, "TestRenderOverlay12k_NoParcels.png", "PNG");
+            RenderDynamicOverlayAndVerifyConvenience(map, "TestRenderOverlay12kConvenience_NoParcels.png", "PNG");
 
             //Turn parcels back on
             parcels = null;
@@ -497,27 +516,10 @@
             map.Save();
 
             //Render again
-            using (var stream = mapSvc.RenderRuntimeMap(map.ResourceID, map.ViewCenter.X, map.ViewCenter.Y, map.ViewScale, map.DisplayWidth, map.DisplayHeight, map.DisplayDpi, "PNG"))
-            {
-                using (var ms = new MemoryStream())
-                using (var ms2 = new MemoryStream())
-                using (var fs = new FileStream("TestRender12k_ParcelsBackOn.png", FileMode.OpenOrCreate))
-                {
-                    Utility.CopyStream(stream, ms);
-                    Utility.CopyStream(ms, ms2);
-                    Utility.CopyStream(ms, fs);
-                    //See if System.Drawing.Image accepts this
-                    try
-                    {
-                        using (var img = System.Drawing.Image.FromStream(ms))
-                        { }
-                    }
-                    catch (Exception ex)
-                    {
-                        Assert.Fail(ex.Message);
-                    }
-                }
-            }
+            RenderAndVerify(mapSvc, map, "TestRender12k_ParcelsBackOn.png", "PNG");
+            RenderAndVerifyConvenience(map, "TestRender12kConvenience_ParcelsBackOn.png", "PNG");
+            RenderDynamicOverlayAndVerify(mapSvc, map, "TestRenderOverlay12k_ParcelsBackOn.png", "PNG");
+            RenderDynamicOverlayAndVerifyConvenience(map, "TestRenderOverlay12kConvenience_ParcelsBackOn.png", "PNG");
         }
 
         public virtual void TestResourceEvents()
@@ -547,6 +549,13 @@
 
         public virtual void TestLargeMapCreatePerformance()
         {
+            TestMapCreate(50, 10);
+            TestMapCreate(100, 25);
+            TestMapCreate(200, 50);
+        }
+
+        private void TestMapCreate(int layerSize, int groupSize)
+        {
             //Create a 200 layer, 50 group map. This is not part of the benchmark
             var mdf = ObjectFactory.CreateMapDefinition(_conn, "LargeMap");
             string root = "Library://UnitTests/LargeMapTest/";
@@ -561,9 +570,9 @@
                 Utility.CopyStream(fs, ms);
             }
 
-            int step = 4;
+            int step = layerSize / groupSize;
             int g = 0;
-            for (int i = 0; i < 200; i++)
+            for (int i = 0; i < layerSize; i++)
             {
                 if (i % step == 0)
                     g++;
@@ -594,13 +603,12 @@
             var map = mapSvc.CreateMap(mid, mdf, 1.0);
             sw.Stop();
 
-            string msg = "Create Map time for 200 layer, 50 group map: " + sw.ElapsedMilliseconds + "ms";
+            string msg = "Create Map time for " + layerSize + " layer, " + groupSize + " group map: " + sw.ElapsedMilliseconds + "ms";
             Trace.WriteLine(msg);
-            Console.WriteLine(msg);
         }
     }
 
-    [TestFixture]
+    [TestFixture(Ignore = true)]
     public class HttpRuntimeMapTests : RuntimeMapTests
     {
         protected override IServerConnection CreateTestConnection()
@@ -648,7 +656,7 @@
         }
     }
 
-    [TestFixture(Ignore = true)]
+    [TestFixture]
     public class LocalRuntimeMapTests : RuntimeMapTests
     {
         protected override IServerConnection CreateTestConnection()
@@ -660,6 +668,12 @@
         }
 
         [Test]
+        public override void TestResourceEvents()
+        {
+            base.TestResourceEvents();
+        }
+
+        [Test]
         public override void TestCreate()
         {
             base.TestCreate();


Property changes on: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI
___________________________________________________________________
Modified: svn:ignore
   - bin
obj

   + bin
obj
*.user


Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/CommandType.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/CommandType.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/CommandType.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -28,5 +28,6 @@
     /// </summary>
     public enum CommandType : int
     {
+        GetResourceContents
     }
 }

Added: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/IGetResourceContents.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/IGetResourceContents.cs	                        (rev 0)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Commands/IGetResourceContents.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -0,0 +1,39 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using OSGeo.MapGuide.MaestroAPI.Resource;
+
+namespace OSGeo.MapGuide.MaestroAPI.Commands
+{
+    /// <summary>
+    /// Defines a command to get a set of resource contents in a single batch
+    /// </summary>
+    public interface IGetResourceContents : ICommand
+    {
+        /// <summary>
+        /// Gets the resource content of the specified resources
+        /// </summary>
+        /// <param name="resourceIds"></param>
+        /// <returns></returns>
+        Dictionary<string, IResource> Execute(IEnumerable<string> resourceIds);
+    }
+}

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -28,6 +28,8 @@
 using OSGeo.MapGuide.MaestroAPI.Resource;
 using System.ComponentModel;
 using OSGeo.MapGuide.ObjectModels.LayerDefinition;
+using System.Diagnostics;
+using OSGeo.MapGuide.MaestroAPI.Commands;
 
 namespace OSGeo.MapGuide.MaestroAPI.Mapping
 {
@@ -38,8 +40,20 @@
     /// </summary>
     /// <remarks>
     /// If you want to use this instance with the Rendering Service APIs, it is important to set the correct
-    /// meters per unit value before calling the <see cref="OSGeo.MapGuide.MaestroAPI.Mapping.RuntimeMap.Save"/> method, as an incorrect meters
+    /// meters per unit value before calling the <see cref="T:OSGeo.MapGuide.MaestroAPI.Mapping.RuntimeMap.Save"/> method, as an incorrect meters
     /// per unit value will produce incorrect images. 
+    /// 
+    /// Also note that to improve the creation performance, certain implementations of <see cref="T:OSGeo.MapGuide.MaestroAPI.IServerConnection"/>
+    /// offer a <see cref="T:OSGeo.MapGuide.MaestroAPI.Mapping.IRuntimeMapSetup"/> helper to return a series of layer definitions in a batch (fetching
+    /// layer definitions one at a time is the main performance bottleneck for large maps), batching can improve creation times by:
+    /// 
+    ///  - HTTP: 2x
+    ///  - Local: 3x (if using MapGuide 2.2 APIs. As this takes advantage of the GetResourceContents() API introduced in 2.2). For older versions of MapGuide there is no batching.
+    /// 
+    /// In particular, the HTTP implementation of <see cref="T:OSGeo.MapGuide.MaestroAPI.IServerConection"/> uses the <see cref="T:System.Threading.ThreadPool"/>
+    /// class to fetch multiple layer definitions in parallel. If your code uses this implementation, be aware of this face and the performance implications
+    /// involved, as an excessively large thread pool size may negatively affect stability of your MapGuide Server.
+    /// 
     /// </remarks>
     /// <example>
     /// How to create a <see cref="RuntimeMap"/> with the correct meters per unit value using the MgCoordinateSystem API
@@ -123,6 +137,9 @@
         /// </summary>
         protected Dictionary<string, RuntimeMapLayer> _layerIdMap;
 
+        private IMappingService _mapSvc;
+        private IGetResourceContents _getRes;
+
         internal RuntimeMap(IServerConnection conn)
         {
             _disableChangeTracking = true;
@@ -134,24 +151,46 @@
             _finiteDisplayScales = new double[0];
             this.ResourceService = conn.ResourceService;
             this.FeatureService = conn.FeatureService;
+            if (Array.IndexOf(conn.Capabilities.SupportedServices, (int)ServiceType.Mapping) >= 0)
+            {
+                _mapSvc = (IMappingService)conn.GetService((int)ServiceType.Mapping);
+            }
+            if (Array.IndexOf(conn.Capabilities.SupportedCommands, (int)CommandType.GetResourceContents) >= 0)
+            {
+                _getRes = (IGetResourceContents)conn.CreateCommand((int)CommandType.GetResourceContents);
+            }
             _layers = new List<RuntimeMapLayer>();
             _groups = new List<RuntimeMapGroup>();
             _layerIdMap = new Dictionary<string, RuntimeMapLayer>();
             this.Selection = new MapSelection(this);
         }
 
+        static IEnumerable<string> GetLayerIds(IMapDefinition mdf)
+        {
+            foreach (var layer in mdf.MapLayer)
+            {
+                yield return layer.ResourceId;
+            }
+            if (mdf.BaseMap != null)
+            {
+                foreach (var group in mdf.BaseMap.BaseMapLayerGroup)
+                {
+                    foreach (var layer in group.BaseMapLayer)
+                    {
+                        yield return layer.ResourceId;
+                    }
+                }
+            }
+        }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="RuntimeMap"/> class.
         /// </summary>
         /// <param name="mdf">The map definition to create this map from.</param>
+        /// <param name="metersPerUnit">The meters per unit value</param>
         internal RuntimeMap(IMapDefinition mdf, double metersPerUnit)
             : this(mdf.CurrentConnection)
         {
-            //TODO: Performance would be greatly improved if we can take advantage of
-            //the new GetResourceContents() API in 2.2. But can we do this via the combination
-            //of reflection and assembly binding redirection seeing as we are referencing
-            //a 2.0.x assembly?
-
             this.MetersPerUnit = metersPerUnit;
 
             this.MapDefinition = mdf.ResourceID;
@@ -159,9 +198,26 @@
             this.DataExtent = mdf.Extents.Clone();
             this.BackgroundColor = mdf.BackgroundColor;
             this.CoordinateSystem = mdf.CoordinateSystem;
-            this.MetersPerUnit = 1.0;
+            
             //TODO: infer real mpu from coordinate system
 
+            //If a setup helper exists, use it to get required layers in a single
+            //batch. Eliminating lots of chatter for really large maps.
+            if (_getRes != null)
+            {
+                Trace.TraceInformation("[RuntimeMap.ctor]: Batching layer requests");
+                var res = _getRes.Execute(GetLayerIds(mdf));
+                //Pre-populate layer def cache so GetLayerDefinition() returns these
+                //instead of making a new request
+                foreach (var key in res.Keys)
+                {
+                    var layer = res[key] as ILayerDefinition;
+                    if (layer != null)
+                        layerDefinitionCache.Add(key, layer);
+                }
+                Trace.TraceInformation("[RuntimeMap.ctor]: {0} layers pre-cached", layerDefinitionCache.Count);
+            }
+
             int dispIndex = 0;
             //Load map layers
             foreach (var layer in mdf.MapLayer)
@@ -1181,5 +1237,46 @@
         }
 
         #endregion
+
+        #region convenience methods
+        /// <summary>
+        /// Convenience method for rendering a bitmap of the current map
+        /// </summary>
+        /// <param name="format"></param>
+        /// <returns></returns>
+        public System.IO.Stream Render(string format)
+        {
+            if (_mapSvc == null)
+                throw new NotSupportedException();
+
+            return _mapSvc.RenderRuntimeMap(
+                this.ResourceID, 
+                this.ViewCenter.X, 
+                this.ViewCenter.Y, 
+                this.ViewScale, 
+                this.DisplayWidth, 
+                this.DisplayHeight, 
+                this.DisplayDpi, 
+                format);
+        }
+
+        /// <summary>
+        /// Convenience method for rendering a dynamic overlay of the current map
+        /// </summary>
+        /// <param name="format"></param>
+        /// <param name="keepSelection"></param>
+        /// <returns></returns>
+        public System.IO.Stream RenderDynamicOverlay(string format, bool keepSelection)
+        {
+            if (_mapSvc == null)
+                throw new NotSupportedException();
+
+            return _mapSvc.RenderDynamicOverlay(
+                this,
+                this.Selection,
+                format,
+                keepSelection);
+        }
+        #endregion
     }
 }

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2010-12-02 09:59:15 UTC (rev 5431)
@@ -167,6 +167,7 @@
       <Link>GlobalAssemblyInfo.cs</Link>
     </Compile>
     <Compile Include="BindingListExtensions.cs" />
+    <Compile Include="Commands\IGetResourceContents.cs" />
     <Compile Include="Capability\ConnectionCapabilities.cs" />
     <Compile Include="Check.cs" />
     <Compile Include="Commands\CommandType.cs" />

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -55,9 +55,9 @@
         /// <returns></returns>
         RuntimeMap OpenMap(string runtimeMapResourceId);
 
-        //System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format);
+        System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format);
 
-        //System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection);
+        System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection);
 
         /// <summary>
         /// Renders the runtime map.

Added: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/Commands/HttpGetResourceContents.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/Commands/HttpGetResourceContents.cs	                        (rev 0)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/Commands/HttpGetResourceContents.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -0,0 +1,99 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+using OSGeo.MapGuide.MaestroAPI.Services;
+using OSGeo.MapGuide.MaestroAPI.Resource;
+using System.Net;
+using System.Threading;
+using System.Diagnostics;
+using OSGeo.MapGuide.MaestroAPI.Commands;
+
+namespace OSGeo.MapGuide.MaestroAPI.Http.Commands
+{
+    public class HttpGetResourceContents : IGetResourceContents
+    {
+        private readonly IResourceService _resSvc;
+
+        public HttpGetResourceContents(IResourceService resSvc)
+        {
+            _resSvc = resSvc;
+            _completed = new Dictionary<string, IResource>();
+        }
+
+        private Dictionary<string, IResource> _completed;
+
+        private readonly object SyncRoot = new object();
+
+        private void PutCompleted(IResource res)
+        {
+            lock (SyncRoot)
+            {
+                _completed.Add(res.ResourceID, res);
+            }
+        }
+
+        public Dictionary<string, IResource> Execute(IEnumerable<string> resourceIds)
+        {
+            _completed.Clear();
+            List<string> workItems = new List<string>(resourceIds);
+            int completed = 0;
+
+            foreach (var resId in workItems)
+            {
+                //Closures referencing iterator variables are bad mmkay?
+                string rid = resId;
+
+                //NOTE: Multi-threaded code is my weakness. So I wouldn't be surprised
+                //if this has some subtle bug due to multi-threading. However, I have
+                //stuck to basic rules of thumb in implementing this (ie. Do not let threads
+                //manipulate shared state!). The whole code path of the 
+                //IResourceService.GetResource() implementation does not touch any shared 
+                //state. So I say with minor confidence that this should work without problems.
+                ThreadPool.QueueUserWorkItem((obj) =>
+                {
+                    try
+                    {
+                        IResource res = _resSvc.GetResource(rid);
+                        PutCompleted(res);
+                    }
+                    finally
+                    {
+                        Interlocked.Increment(ref completed);
+                    }
+                });
+            }
+
+            //Wait until all completed
+            while (completed < workItems.Count)
+                Thread.Sleep(20);
+
+            return _completed;
+        }
+
+        public IServerConnection Parent
+        {
+            get;
+            private set;
+        }
+    }
+}

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -23,6 +23,7 @@
 using OSGeo.MapGuide.MaestroAPI.Services;
 using OSGeo.MapGuide.MaestroAPI.Exceptions;
 using OSGeo.MapGuide.MaestroAPI.Capability;
+using OSGeo.MapGuide.MaestroAPI.Commands;
 
 namespace OSGeo.MapGuide.MaestroAPI.Http
 {
@@ -37,6 +38,7 @@
                 //TODO: Work out what this can/can't do
                 return new int[] 
                 {
+                    (int)CommandType.GetResourceContents
                 };
             }
         }

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -39,6 +39,7 @@
 using System.Text;
 using System.Collections.Generic;
 using OSGeo.MapGuide.ObjectModels.ApplicationDefinition_1_0_0;
+using OSGeo.MapGuide.MaestroAPI.Http.Commands;
 
 namespace OSGeo.MapGuide.MaestroAPI
 {
@@ -68,7 +69,6 @@
 		internal HttpServerConnection()
 			: base()
 		{
-			//m_wc = new WebClient();
 			m_cachedProviderCapabilities = new Hashtable();
 		}
 
@@ -851,7 +851,12 @@
             {
                 Utility.CopyStream(ms, rs);
                 rs.Flush();
-                return req.GetResponse().GetResponseStream();
+                var resp = req.GetResponse();
+                var hwr = resp as HttpWebResponse;
+                if (hwr != null)
+                    LogResponse(hwr);
+
+                return resp.GetResponseStream();
             }
         }
 
@@ -874,7 +879,13 @@
 			{
 				Utility.CopyStream(ms, rs);
 				rs.Flush();
-				return req.GetResponse().GetResponseStream();
+				var resp = req.GetResponse();
+
+                var hwr = resp as HttpWebResponse;
+                if (hwr != null)
+                    LogResponse(hwr);
+
+                return resp.GetResponseStream();
 			}
 
 #endif
@@ -899,7 +910,13 @@
 			{
 				Utility.CopyStream(ms, rs);
 				rs.Flush();
-				return req.GetResponse().GetResponseStream();
+                var resp = req.GetResponse();
+                var hwr = resp as HttpWebResponse;
+
+                if (hwr != null)
+                    LogResponse(hwr);
+    
+                return resp.GetResponseStream();
 			}
 
 #endif
@@ -1443,12 +1460,22 @@
 
         public const string PROP_USER_AGENT = "UserAgent";
         public const string PROP_BASE_URL = "BaseUrl";
-
+       
         public override string[] GetCustomPropertyNames()
         {
             return new string[] { PROP_USER_AGENT, PROP_BASE_URL };
         }
 
+        /// <summary>
+        /// Gets or sets the number of worker threads to spawn when initializing
+        /// a runtime map
+        /// </summary>
+        public int RuntimeMapWorkerCount
+        {
+            get;
+            set;
+        }
+
         public override Type GetCustomPropertyType(string name)
         {
             if (name == PROP_USER_AGENT)
@@ -1655,5 +1682,13 @@
                 return this.DeserializeObject<SiteInformation>(s);
             }
         }
+
+        public override ICommand CreateCommand(int cmdType)
+        {
+            CommandType ct = (CommandType)cmdType;
+            if (ct == CommandType.GetResourceContents)
+                return new HttpGetResourceContents(this);
+            return base.CreateCommand(cmdType);
+        }
     }
 }

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj	2010-12-02 09:59:15 UTC (rev 5431)
@@ -46,6 +46,7 @@
     <Compile Include="HttpCoordinateSystemCatalog.cs" />
     <Compile Include="HttpCoordinateSystemCategory.cs" />
     <Compile Include="HttpServerConnection.cs" />
+    <Compile Include="Commands\HttpGetResourceContents.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="RequestBuilder.cs" />
     <Compile Include="XmlAggregateSetReader.cs" />

Added: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/Commands/LocalGetResourceContents.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/Commands/LocalGetResourceContents.cs	                        (rev 0)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/Commands/LocalGetResourceContents.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -0,0 +1,94 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using OSGeo.MapGuide.MaestroAPI.Commands;
+using OSGeo.MapGuide.MaestroAPI.Resource;
+using System.Diagnostics;
+using System.IO;
+
+namespace OSGeo.MapGuide.MaestroAPI.Native.Commands
+{
+    public class LocalGetResourceContents : IGetResourceContents
+    {
+        private MgResourceService _resSvc;
+
+        public LocalGetResourceContents(LocalNativeConnection conn)
+        {
+            this.Parent = conn;
+            _resSvc = (MgResourceService)conn.Connection.CreateService(MgServiceType.ResourceService);
+        }
+
+        Dictionary<string, IResource> IGetResourceContents.Execute(IEnumerable<string> resourceIds)
+        {
+            //There is an implicit assumption here that all resource ids check out and that
+            //there is no duplicates
+            
+            var resources = new Dictionary<string, IResource>();
+            if (this.Parent.SiteVersion >= new Version(2, 2))
+            {
+                Trace.TraceInformation("[GetResources]: Using optimal code path provided by 2.2 Resource Service APIs");
+
+                MgStringCollection ids = new MgStringCollection();
+                foreach (var rid in resourceIds)
+                {
+                    ids.Add(rid);
+                }
+                //Use the magic of reflection to call newer APIs even though we're referencing
+                //and older assembly
+                System.Reflection.MethodInfo mi = _resSvc.GetType().GetMethod("GetResourceContents");
+                MgStringCollection result = (MgStringCollection)mi.Invoke(_resSvc, new object[] { ids, null });
+
+                int rcount = ids.GetCount();
+                for (int i = 0; i < rcount; i++)
+                {
+                    var resId = ids.GetItem(i);
+                    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(result.GetItem(i))))
+                    {
+                        ResourceTypes resType = ResourceIdentifier.GetResourceType(resId);
+
+                        IResource r = ResourceTypeRegistry.Deserialize(resType, ms);
+                        r.CurrentConnection = this.Parent;
+                        r.ResourceID = resId;
+                        resources.Add(resId, r);
+                    }
+                }
+            }
+            else
+            {
+                //TODO: Maybe use a ThreadPool in conjunction with cloned connections?
+                Trace.TraceInformation("[GetResources]: Using non-optimal code path provided by pre-2.2 Resource Service APIs");
+                foreach (var rid in resourceIds)
+                {
+                    resources.Add(rid, this.Parent.ResourceService.GetResource(rid));
+                }
+            }
+
+            return resources;
+        }
+
+        public IServerConnection Parent
+        {
+            get;
+            private set;
+        }
+    }
+}

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeCapabilities.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeCapabilities.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeCapabilities.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -22,6 +22,7 @@
 using System.Text;
 using OSGeo.MapGuide.MaestroAPI.Services;
 using OSGeo.MapGuide.MaestroAPI.Capability;
+using OSGeo.MapGuide.MaestroAPI.Commands;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
@@ -33,10 +34,21 @@
         {
             get
             {
-                //TODO: Work out what this can/can't do
-                return new int[] 
+                if (_parent.SiteVersion >= new Version(2, 2))
                 {
-                };
+                    //TODO: Work out what this can/can't do
+                    return new int[] 
+                    {
+                        (int)CommandType.GetResourceContents
+                    };
+                }
+                else
+                {
+                    //TODO: Work out what this can/can't do
+                    return new int[] 
+                    {
+                    };
+                }
             }
         }
 

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs	2010-12-02 09:59:15 UTC (rev 5431)
@@ -32,6 +32,9 @@
 using OSGeo.MapGuide.ObjectModels.Common;
 using OSGeo.MapGuide.ObjectModels.MapDefinition;
 using OSGeo.MapGuide.MaestroAPI.Exceptions;
+using System.Diagnostics;
+using OSGeo.MapGuide.MaestroAPI.Commands;
+using OSGeo.MapGuide.MaestroAPI.Native.Commands;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
@@ -119,7 +122,7 @@
         /// <summary>
         /// Returns a working copy of the site connection.
         /// </summary>
-        private MgSiteConnection Connection
+        internal MgSiteConnection Connection
         {
             get
             {
@@ -578,6 +581,22 @@
             return Utility.MgStreamToNetStream(rnd, rnd.GetType().GetMethod("RenderMap", types), args);
         }
 
+        public override Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection)
+        {
+            MgRenderingService rnd = this.Connection.CreateService(MgServiceType.RenderingService) as MgRenderingService;
+            MgResourceService res = this.Connection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+
+            MgMap mmap = new MgMap();
+            mmap.Open(res, map.Name);
+            MgSelection sel = new MgSelection(mmap);
+            if (selection != null)
+                sel.FromXml(selection.ToXml());
+
+            object[] args = new object[] { mmap, sel, format, keepSelection };
+            Type[] types = new Type[] { args[0].GetType(), args[1].GetType(), args[2].GetType(), args[3].GetType() };
+            return Utility.MgStreamToNetStream(rnd, rnd.GetType().GetMethod("RenderDynamicOverlay", types), args);
+        }
+
 		public override bool IsSessionExpiredException(Exception ex)
 		{
 			return ex != null && ex.GetType() == typeof(OSGeo.MapGuide.MgSessionExpiredException) ||  ex.GetType() == typeof(OSGeo.MapGuide.MgSessionNotFoundException);
@@ -805,9 +824,12 @@
             get { return this; }
         }
 
-        public OSGeo.MapGuide.MaestroAPI.Commands.ICommand CreateCommand(int commandType)
+        public override OSGeo.MapGuide.MaestroAPI.Commands.ICommand CreateCommand(int cmdType)
         {
-            throw new NotImplementedException();
+            CommandType ct = (CommandType)cmdType;
+            if (ct == CommandType.GetResourceContents)
+                return new LocalGetResourceContents(this);
+            return base.CreateCommand(cmdType);
         }
 
         private IConnectionCapabilities _caps;
@@ -1081,10 +1103,5 @@
             var dwSvc = (MgDrawingService)this.Connection.CreateService(MgServiceType.DrawingService);
             return Utility.MgStreamToNetStream(dwSvc, dwSvc.GetType().GetMethod("GetSectionResource"), new object[] { new MgResourceIdentifier(resourceID), resourceName });
         }
-
-        public override Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection)
-        {
-            throw new NotImplementedException();
-        }
     }
 }

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/OSGeo.MapGuide.MaestroAPI.Native.csproj
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/OSGeo.MapGuide.MaestroAPI.Native.csproj	2010-12-02 06:45:19 UTC (rev 5430)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI.Native/OSGeo.MapGuide.MaestroAPI.Native.csproj	2010-12-02 09:59:15 UTC (rev 5431)
@@ -52,6 +52,7 @@
     <Compile Include="..\Properties\GlobalAssemblyInfo.cs">
       <Link>GlobalAssemblyInfo.cs</Link>
     </Compile>
+    <Compile Include="Commands\LocalGetResourceContents.cs" />
     <Compile Include="MgReadOnlyStream.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="LocalNativeCapabilities.cs" />
@@ -68,9 +69,6 @@
       <Name>OSGeo.MapGuide.MaestroAPI</Name>
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup>
-    <Folder Include="Commands\" />
-  </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.



More information about the mapguide-commits mailing list