From 9906eee3bdff926da59b8ed4ae4632e57cda9329 Mon Sep 17 00:00:00 2001 From: James South Date: Sat, 16 Aug 2014 18:36:21 +0100 Subject: [PATCH] Adding PostProcessingEventHandler Fixes #74 Former-commit-id: 00d48c497c41c1e8bc2c56a1865338c1a21ec503 --- ...ncDeDuperLock.cs => AsyncDuplicateLock.cs} | 32 +++++++++---------- .../Helpers/PostProcessingEventArgs.cs | 25 +++++++++++++++ .../HttpModules/ImageProcessingModule.cs | 27 ++++++++++++---- .../ImageProcessor.Web.csproj | 3 +- .../Imaging/Formats/JpegFormat.cs | 2 +- src/TestWebsites/MVC/Global.asax.cs | 7 ++++ 6 files changed, 72 insertions(+), 24 deletions(-) rename src/ImageProcessor.Web/Helpers/{AsyncDeDuperLock.cs => AsyncDuplicateLock.cs} (80%) create mode 100644 src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs diff --git a/src/ImageProcessor.Web/Helpers/AsyncDeDuperLock.cs b/src/ImageProcessor.Web/Helpers/AsyncDuplicateLock.cs similarity index 80% rename from src/ImageProcessor.Web/Helpers/AsyncDeDuperLock.cs rename to src/ImageProcessor.Web/Helpers/AsyncDuplicateLock.cs index f436b5442..47f14c81c 100644 --- a/src/ImageProcessor.Web/Helpers/AsyncDeDuperLock.cs +++ b/src/ImageProcessor.Web/Helpers/AsyncDuplicateLock.cs @@ -1,5 +1,5 @@ // -------------------------------------------------------------------------------------------------------------------- -// +// // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // @@ -18,24 +18,24 @@ namespace ImageProcessor.Web.Helpers /// Throttles duplicate requests. /// Based loosely on /// - public sealed class AsyncDeDuperLock + public sealed class AsyncDuplicateLock { /// - /// The semaphore slims. + /// The collection of semaphore slims. /// - private static readonly ConcurrentDictionary SemaphoreSlims - = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary SemaphoreSlims + = new ConcurrentDictionary(); /// - /// The lock. + /// Locks against the given key. /// /// - /// The hash. + /// The key that identifies the current object. /// /// - /// The . + /// The disposable . /// - public IDisposable Lock(string key) + public IDisposable Lock(object key) { DisposableScope releaser = new DisposableScope( key, @@ -55,15 +55,15 @@ namespace ImageProcessor.Web.Helpers } /// - /// The lock async. + /// Asynchronously locks against the given key. /// /// - /// The key. + /// The key that identifies the current object. /// /// - /// The . + /// The disposable . /// - public Task LockAsync(string key) + public Task LockAsync(object key) { DisposableScope releaser = new DisposableScope( key, @@ -100,12 +100,12 @@ namespace ImageProcessor.Web.Helpers /// /// The key /// - private readonly string key; + private readonly object key; /// /// The close scope action. /// - private readonly Action closeScopeAction; + private readonly Action closeScopeAction; /// /// Initializes a new instance of the class. @@ -116,7 +116,7 @@ namespace ImageProcessor.Web.Helpers /// /// The close scope action. /// - public DisposableScope(string key, Action closeScopeAction) + public DisposableScope(object key, Action closeScopeAction) { this.key = key; this.closeScopeAction = closeScopeAction; diff --git a/src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs b/src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs new file mode 100644 index 000000000..a11fbc069 --- /dev/null +++ b/src/ImageProcessor.Web/Helpers/PostProcessingEventArgs.cs @@ -0,0 +1,25 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The post processing event arguments. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + using System; + + /// + /// The post processing event arguments. + /// + public class PostProcessingEventArgs : EventArgs + { + /// + /// Gets or sets the cached image path. + /// + public string CachedImagePath { get; set; } + } +} diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs index edea79750..a817918c3 100644 --- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs @@ -62,7 +62,7 @@ namespace ImageProcessor.Web.HttpModules /// /// The locker for preventing duplicate requests. /// - private static readonly AsyncDeDuperLock Locker = new AsyncDeDuperLock(); + private static readonly AsyncDuplicateLock Locker = new AsyncDuplicateLock(); /// /// The value to prefix any remote image requests with to ensure they get captured. @@ -108,6 +108,11 @@ namespace ImageProcessor.Web.HttpModules } #endregion + /// + /// The event that is called when a new image is processed. + /// + public static event EventHandler OnPostProcessing; + #region IHttpModule Members /// /// Initializes a module and prepares it to handle requests. @@ -129,12 +134,8 @@ namespace ImageProcessor.Web.HttpModules preserveExifMetaData = ImageProcessorConfiguration.Instance.PreserveExifMetaData; } -#if NET45 && !__MonoCS__ EventHandlerTaskAsyncHelper wrapper = new EventHandlerTaskAsyncHelper(this.PostAuthorizeRequest); context.AddOnPostAuthorizeRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler); -#else - context.PostAuthorizeRequest += this.PostAuthorizeRequest; -#endif context.PreSendRequestHeaders += this.ContextPreSendRequestHeaders; } @@ -385,6 +386,13 @@ namespace ImageProcessor.Web.HttpModules // Trim the cache. await cache.TrimCachedFolderAsync(cachedPath); + // Fire the post processing event. + EventHandler handler = OnPostProcessing; + if (handler != null) + { + handler.Invoke(this, new PostProcessingEventArgs() { CachedImagePath = cachedPath }); + } + // Store the response type and cache dependency in the context for later retrieval. context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType; context.Items[CachedResponseFileDependency] = new List { cachedPath }; @@ -418,6 +426,13 @@ namespace ImageProcessor.Web.HttpModules // Trim the cache. await cache.TrimCachedFolderAsync(cachedPath); + // Fire the post processing event. + EventHandler handler = OnPostProcessing; + if (handler != null) + { + handler.Invoke(this, new PostProcessingEventArgs() { CachedImagePath = cachedPath }); + } + // Store the response type and cache dependencies in the context for later retrieval. context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType; context.Items[CachedResponseFileDependency] = new List { requestPath, cachedPath }; @@ -467,7 +482,7 @@ namespace ImageProcessor.Web.HttpModules } else if (isRemote) { - // Just repoint to the external url. + // Just re-point to the external url. HttpContext.Current.Response.Redirect(requestPath); } } diff --git a/src/ImageProcessor.Web/ImageProcessor.Web.csproj b/src/ImageProcessor.Web/ImageProcessor.Web.csproj index f13068324..2ab412092 100644 --- a/src/ImageProcessor.Web/ImageProcessor.Web.csproj +++ b/src/ImageProcessor.Web/ImageProcessor.Web.csproj @@ -56,8 +56,9 @@ - + + diff --git a/src/ImageProcessor/Imaging/Formats/JpegFormat.cs b/src/ImageProcessor/Imaging/Formats/JpegFormat.cs index f7ff73c66..ae5fd05c3 100644 --- a/src/ImageProcessor/Imaging/Formats/JpegFormat.cs +++ b/src/ImageProcessor/Imaging/Formats/JpegFormat.cs @@ -75,7 +75,7 @@ namespace ImageProcessor.Imaging.Formats { base.ApplyProcessor(processor, factory); - // Set the property item information from any Exif metadata. + // Set the property item information from any Exif metadata. // We do this here so that they can be changed between processor methods. if (factory.PreserveExifData) { diff --git a/src/TestWebsites/MVC/Global.asax.cs b/src/TestWebsites/MVC/Global.asax.cs index 66099ae16..87315956d 100644 --- a/src/TestWebsites/MVC/Global.asax.cs +++ b/src/TestWebsites/MVC/Global.asax.cs @@ -8,6 +8,10 @@ using System.Web.Routing; namespace Test_Website_NET45 { + using System.Diagnostics; + + using ImageProcessor.Web.HttpModules; + // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication @@ -19,6 +23,9 @@ namespace Test_Website_NET45 WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); + + // Test the post processing event. + ImageProcessingModule.OnPostProcessing += (sender, args) => Debug.WriteLine(args.CachedImagePath); } } } \ No newline at end of file