Click here to Skip to main content
15,885,546 members
Articles / Web Development / HTML

Gallery Server Pro - An ASP.NET Gallery for Sharing Photos, Video, Audio and Other Media

Rate me:
Please Sign up or sign in to vote.
4.86/5 (131 votes)
18 Oct 2013GPL331 min read 825.2K   539  
Gallery Server Pro is a complete, stable ASP.NET gallery for sharing photos, video, audio and other media. This article presents the overall architecture and major features.
// Brandon Haynes - http://brandonhaynes.org
// Copyright (c) 2008
// by Brandon Haynes

// Please refer to the project license, located at http://www.codeplex.com/DNNLocalization/license

// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.

//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
//WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
//USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Resources;
using System.Resources.Tools;
using System.Security.Permissions;
using System.Web.Compilation;
using System.Xml;
using System.Xml.Schema;

namespace BrandonHaynes.DotNetNukeResXBuildProvider
{
	public abstract class BaseResourcesBuildProvider : BuildProvider
	{
		#region Protected Properties
		protected bool GenerateStronglyTypedClasses { get; set; }
		protected ResourcePathMetadata Resource { get; set; }
		#endregion

		#region Constructors
		protected BaseResourcesBuildProvider()
		{ GenerateStronglyTypedClasses = true; }
		#endregion

		#region Abstract Members
		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
		protected abstract IResourceReader GetResourceReader(Stream inputStream);
		#endregion

		#region Public Methods

		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
		public override void GenerateCode(AssemblyBuilder assemblyBuilder)
		{
			#region Modification for Gallery Server Pro

			// BEGIN: Code Addition by Roger Martin, 2010-08-31

			// The following can be used to process all .resx files in App_GlobalResources, but this causes issues when language packs are installed.
			//if (!VirtualPath.Contains("App_GlobalResources"))
			//  return;

			if (!VirtualPath.EndsWith("GalleryServerPro.resx"))
				return;

			// END: Code Addition by Roger Martin, 2010-08-31

			// Problem: This original build provider by Brandon Haynes processes all .resx files in an application. However, some modules 
			// (such as Ultra Media Gallery 6.5.2) produce an error when this code processes its local resource files (e.g. for a 
			// particular user control).
			
			// Solution: Modify this function to process only the GalleryServerPro.resx file. This may be problematic if other
			// module developers are using this build provider to process their own .resx files. However, when I change the code to process all
			// .resx files in App_GlobalResource, the following error occurs when a language pack is installed:
			// "The namespace 'Resources' already contains a definition for 'GlobalResources'"

			// Error that occurs when the above code is not included:
			// DotNetNuke.Services.Exceptions.ModuleLoadException: An item with the same key has already been added. ---> 
			// System.Web.HttpParseException: An item with the same key has already been added. ---> 
			// System.ArgumentException: An item with the same key has already been added. at 
			// BrandonHaynes.DotNetNukeResXBuildProvider.BaseResourcesBuildProvider.GenerateCode(AssemblyBuilder assemblyBuilder) in 
			// C:\Documents and Settings\Brandon.DELL\My Documents\My Projects\BrandonHaynes\DotNetNuke ASP.NET Localization BuildProvider\BuildProvider\BaseResourcesBuildProvider.cs:line 70 
			// at System.Web.Compilation.AssemblyBuilder.AddBuildProvider(BuildProvider buildProvider) 
			// --- End of inner exception stack trace --- at System.Web.Compilation.AssemblyBuilder.AddBuildProvider(BuildProvider buildProvider) at 
			// System.Web.Compilation.BuildProvidersCompiler.ProcessBuildProviders() at System.Web.Compilation.BuildProvidersCompiler.PerformBuild() at 
			// System.Web.Compilation.CodeDirectoryCompiler.GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, String assemblyName, 
			// StringSet excludedSubdirectories, Boolean isDirectoryAllowed) at System.Web.Compilation.BuildManager.CompileCodeDirectory(VirtualPath virtualDir, 
			// CodeDirectoryType dirType, String assemblyName, StringSet excludedSubdirectories) at System.Web.Compilation.BuildManager.EnsureFirstTimeDirectoryInit(VirtualPath 
			// virtualDir) at System.Web.Compilation.BuildManager.GetBuildResultFromCacheInternal(String cacheKey, Boolean keyFromVPP, VirtualPath virtualPath, 
			// Int64 hashCode, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, 
			// Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean 
			// allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at 
			// System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean 
			// allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at 
			// System.Web.Compilation.BuildManager.GetVPathBuildResult(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, 
			// Boolean allowBuildInPrecompile, Boolean ensureIsUpToDate) at System.Web.UI.TemplateControl.LoadControl(VirtualPath virtualPath) at 
			// DotNetNuke.UI.ControlUtilities.LoadControl[T](TemplateControl containerControl, String ControlSrc) in 
			// D:\Development\DNN\Library\UI\ControlUtilities.vb:line 61 at DotNetNuke.UI.Modules.ModuleHost.LoadModuleControl() in 
			// D:\Development\DNN\Library\UI\Modules\ModuleHost.vb:line 229 --- End of inner exception stack trace ---

			#endregion

			Resource = new ResourcePathMetadata(VirtualPath);

			using (Stream stream = base.OpenStream())
			{
				var resourceReader = this.GetResourceReader(stream);

				try
				{
					GenerateResourceFile(assemblyBuilder, resourceReader);
				}
				catch (ArgumentException exception)
				{
					throw DereferenceException(exception);
				}

				if (Resource.Culture.Equals(CultureInfo.InvariantCulture) && !Resource.IsLocal && GenerateStronglyTypedClasses)
					GenerateStronglyTypedClass(assemblyBuilder, resourceReader);
			}
		}

		#endregion

		#region Private Methods

		private void GenerateResourceFile(AssemblyBuilder assemblyBuilder, IResourceReader reader)
		{
			using (var stream = assemblyBuilder.CreateEmbeddedResource(this, Resource.EmbeddedName))
			using (var writer = new ResourceWriter(stream))
				foreach (DictionaryEntry entry in reader)
					writer.AddResource(entry.Key.ToString(), entry.Value);
		}

		private void GenerateStronglyTypedClass(AssemblyBuilder assemblyBuilder, IResourceReader reader)
		{
			IDictionary resourceList;
			string[] unmatchableElements;

			using (reader)
				resourceList = GetResourceList(reader);

			var code = StronglyTypedResourceBuilder.Create(resourceList, Resource.TypeName, Resource.Namespace, assemblyBuilder.CodeDomProvider, false, out unmatchableElements);
			assemblyBuilder.AddCodeCompileUnit(this, code.Adapt(Resource));
		}

		private static IDictionary GetResourceList(IResourceReader reader)
		{
			return reader
				.Cast<DictionaryEntry>()
				.ToDictionary(entry => entry.Key, entry => entry.Value);
		}

		private static Exception DereferenceException(Exception exception)
		{
			if (exception.InnerException == null || (!(exception.InnerException is XmlException) && !(exception.InnerException is XmlSchemaException)))
				return exception;

			return exception.InnerException;
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer (Senior) Tech Info Systems
United States United States
I have nearly 20 years of industry experience in software development, architecture, and Microsoft Office products. My company Tech Info Systems provides custom software development services for corporations, governments, and other organizations. Tech Info Systems is a registered member of the Microsoft Partner Program and I am a Microsoft Certified Professional Developer (MCPD).

I am the creator and lead developer of Gallery Server Pro, a free, open source ASP.NET gallery for sharing photos, video, audio, documents, and other files over the web. It has been developed over several years and has involved thousands of hours. The end result is a robust, configurable, and professional grade gallery that can be integrated into your web site, whether you are a large corporation, small business, professional photographer, or a local church.

Comments and Discussions