From 81021f5821bd8a6d8e9672d384946b7a60951390 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Mon, 18 Feb 2013 15:46:18 -0100 Subject: [PATCH 1/4] Part of the fix for U4-1689 Adds an alternative to the naming of the media subfolders instead of using the PropertyId. --- src/Umbraco.Core/Media/MediaSubFolders.cs | 60 +++++++++++++++++++ src/Umbraco.Core/Models/ContentExtensions.cs | 6 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../businesslogic/datatype/FileHandlerData.cs | 7 ++- 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 src/Umbraco.Core/Media/MediaSubFolders.cs diff --git a/src/Umbraco.Core/Media/MediaSubFolders.cs b/src/Umbraco.Core/Media/MediaSubFolders.cs new file mode 100644 index 0000000000..ab5e994e73 --- /dev/null +++ b/src/Umbraco.Core/Media/MediaSubFolders.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Umbraco.Core.IO; + +namespace Umbraco.Core.Media +{ + /// + /// Internal singleton to handle the numbering of subfolders within the Media-folder. + /// When this class is initiated it will look for numbered subfolders and select the highest number, + /// which will be the start point for the naming of the next subfolders. If no subfolders exists + /// then the starting point will be 1000, ie. /media/1000/koala.jpg + /// + internal class MediaSubFolders + { + #region Singleton + + private long _numberedFolder = 1000;//Default starting point + private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim(); + private static readonly Lazy Lazy = new Lazy(() => new MediaSubFolders()); + + public static MediaSubFolders Current { get { return Lazy.Value; } } + + private MediaSubFolders() + { + var folders = new List(); + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); + var directories = fs.GetDirectories("/"); + if (directories.Any()) + { + foreach (var directory in directories) + { + long dirNum; + if (long.TryParse(directory, out dirNum)) + { + folders.Add(dirNum); + } + } + long last = folders.OrderBy(x => x).Last(); + _numberedFolder = last; + } + } + + #endregion + + /// + /// Returns an increment of the numbered media subfolders. + /// + /// A value + public long Increment() + { + using (new ReadLock(ClearLock)) + { + _numberedFolder++; + return _numberedFolder; + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 788dccc285..2aca92d857 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -10,6 +10,7 @@ using System.Xml; using System.Xml.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.Media; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; @@ -109,9 +110,10 @@ namespace Umbraco.Core.Models return; bool supportsResizing = false; + var numberedFolder = MediaSubFolders.Current.Increment(); string fileName = UmbracoSettings.UploadAllowDirectories - ? Path.Combine(property.Id.ToString(), name) - : property.Id + "-" + name; + ? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), name) + : numberedFolder + "-" + name; string extension = Path.GetExtension(name); var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 9ac549c3e4..a915caf4e4 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -139,6 +139,7 @@ + diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index b19ca3f14a..854abd2d77 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -1,8 +1,10 @@ using System; +using System.Globalization; using System.IO; using System.Web; using System.Xml; using Umbraco.Core.IO; +using Umbraco.Core.Media; using umbraco.cms.businesslogic.Files; using umbraco.cms.businesslogic.property; @@ -55,9 +57,10 @@ namespace umbraco.cms.businesslogic.datatype // handle upload if (name != String.Empty) { + var numberedFolder = MediaSubFolders.Current.Increment(); string fileName = UmbracoSettings.UploadAllowDirectories - ? Path.Combine(PropertyId.ToString(), name) - : PropertyId + "-" + name; + ? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), name) + : numberedFolder + "-" + name; //fileName = Path.Combine(SystemDirectories.Media, fileName); UmbracoFile um = UmbracoFile.Save(fileStream, fileName); From ec4b1c8f701a6c2dde0343d9985911762aed1c9f Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Tue, 19 Feb 2013 11:06:00 -0100 Subject: [PATCH 2/4] Fixes U4-1689 and U4-1719. Refactoring UmbracoImageMediaFactory so it uses the extension method for uploading/setting images, so its a bit more DRY. --- src/Umbraco.Core/IO/MediaFileSystem.cs | 11 +- ...SubFolders.cs => MediaSubfolderCounter.cs} | 28 ++-- src/Umbraco.Core/Models/ContentExtensions.cs | 59 +++++-- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../businesslogic/datatype/FileHandlerData.cs | 2 +- .../media/UmbracoImageMediaFactory.cs | 158 ++---------------- 6 files changed, 80 insertions(+), 180 deletions(-) rename src/Umbraco.Core/Media/{MediaSubFolders.cs => MediaSubfolderCounter.cs} (65%) diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index e3d8f489c6..de795303af 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using Umbraco.Core.CodeAnnotations; using Umbraco.Core.Configuration; namespace Umbraco.Core.IO @@ -27,6 +25,15 @@ namespace Umbraco.Core.IO return propertyId.ToString() + seperator + fileName; } + public string GetRelativePath(string subfolder, string fileName) + { + var seperator = UmbracoSettings.UploadAllowDirectories + ? Path.DirectorySeparatorChar + : '-'; + + return subfolder + seperator + fileName; + } + public IEnumerable GetThumbnails(string path) { var parentDirectory = System.IO.Path.GetDirectoryName(path); diff --git a/src/Umbraco.Core/Media/MediaSubFolders.cs b/src/Umbraco.Core/Media/MediaSubfolderCounter.cs similarity index 65% rename from src/Umbraco.Core/Media/MediaSubFolders.cs rename to src/Umbraco.Core/Media/MediaSubfolderCounter.cs index ab5e994e73..6f0142cacf 100644 --- a/src/Umbraco.Core/Media/MediaSubFolders.cs +++ b/src/Umbraco.Core/Media/MediaSubfolderCounter.cs @@ -12,34 +12,32 @@ namespace Umbraco.Core.Media /// which will be the start point for the naming of the next subfolders. If no subfolders exists /// then the starting point will be 1000, ie. /media/1000/koala.jpg /// - internal class MediaSubFolders + internal class MediaSubfolderCounter { #region Singleton private long _numberedFolder = 1000;//Default starting point private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim(); - private static readonly Lazy Lazy = new Lazy(() => new MediaSubFolders()); + private static readonly Lazy Lazy = new Lazy(() => new MediaSubfolderCounter()); - public static MediaSubFolders Current { get { return Lazy.Value; } } + public static MediaSubfolderCounter Current { get { return Lazy.Value; } } - private MediaSubFolders() + private MediaSubfolderCounter() { var folders = new List(); var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); - var directories = fs.GetDirectories("/"); - if (directories.Any()) + var directories = fs.GetDirectories(""); + foreach (var directory in directories) { - foreach (var directory in directories) + long dirNum; + if (long.TryParse(directory, out dirNum)) { - long dirNum; - if (long.TryParse(directory, out dirNum)) - { - folders.Add(dirNum); - } + folders.Add(dirNum); } - long last = folders.OrderBy(x => x).Last(); - _numberedFolder = last; } + var last = folders.OrderBy(x => x).LastOrDefault(); + if(last != default(long)) + _numberedFolder = last; } #endregion @@ -52,7 +50,7 @@ namespace Umbraco.Core.Media { using (new ReadLock(ClearLock)) { - _numberedFolder++; + _numberedFolder = _numberedFolder + 1; return _numberedFolder; } } diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 2aca92d857..1ad73191f3 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -58,16 +58,22 @@ namespace Umbraco.Core.Models /// /// Sets and uploads the file from a HttpPostedFileBase object as the property value /// - /// to add property value to + /// to add property value to /// Alias of the property to save the value on /// The containing the file that will be uploaded public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value) { + // Ensure we get the filename without the path in IE in intranet mode + // http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie + var fileName = value.FileName; + if (fileName.LastIndexOf(@"\") > 0) + fileName = fileName.Substring(fileName.LastIndexOf(@"\") + 1); + var name = IOHelper.SafeFileName( - value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, - value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) - .ToLower()); + fileName.Substring(fileName.LastIndexOf(IOHelper.DirSepChar) + 1, + fileName.Length - fileName.LastIndexOf(IOHelper.DirSepChar) - 1) + .ToLower()); if (string.IsNullOrEmpty(name) == false) SetFileOnContent(content, propertyTypeAlias, name, value.InputStream); @@ -76,16 +82,22 @@ namespace Umbraco.Core.Models /// /// Sets and uploads the file from a HttpPostedFile object as the property value /// - /// to add property value to + /// to add property value to /// Alias of the property to save the value on /// The containing the file that will be uploaded public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFile value) { + // Ensure we get the filename without the path in IE in intranet mode + // http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie + var fileName = value.FileName; + if (fileName.LastIndexOf(@"\") > 0) + fileName = fileName.Substring(fileName.LastIndexOf(@"\") + 1); + var name = IOHelper.SafeFileName( - value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, - value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) - .ToLower()); + fileName.Substring(fileName.LastIndexOf(IOHelper.DirSepChar) + 1, + fileName.Length - fileName.LastIndexOf(IOHelper.DirSepChar) - 1) + .ToLower()); if (string.IsNullOrEmpty(name) == false) SetFileOnContent(content, propertyTypeAlias, name, value.InputStream); @@ -94,13 +106,33 @@ namespace Umbraco.Core.Models /// /// Sets and uploads the file from a HttpPostedFileWrapper object as the property value /// - /// to add property value to + /// to add property value to /// Alias of the property to save the value on /// The containing the file that will be uploaded public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileWrapper value) { - if (string.IsNullOrEmpty(value.FileName) == false) - SetFileOnContent(content, propertyTypeAlias, value.FileName, value.InputStream); + // Ensure we get the filename without the path in IE in intranet mode + // http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie + var fileName = value.FileName; + if (fileName.LastIndexOf(@"\") > 0) + fileName = fileName.Substring(fileName.LastIndexOf(@"\") + 1); + + if (string.IsNullOrEmpty(fileName) == false) + SetFileOnContent(content, propertyTypeAlias, fileName, value.InputStream); + } + + /// + /// Sets and uploads the file from a as the property value + /// + /// to add property value to + /// Alias of the property to save the value on + /// Name of the file + /// to save to disk + public static void SetValue(this IContentBase content, string propertyTypeAlias, string fileName, + Stream fileStream) + { + if (string.IsNullOrEmpty(fileName) == false && fileStream != null) + SetFileOnContent(content, propertyTypeAlias, fileName, fileStream); } private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string name, Stream fileStream) @@ -110,11 +142,12 @@ namespace Umbraco.Core.Models return; bool supportsResizing = false; - var numberedFolder = MediaSubFolders.Current.Increment(); + var numberedFolder = MediaSubfolderCounter.Current.Increment(); string fileName = UmbracoSettings.UploadAllowDirectories ? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), name) : numberedFolder + "-" + name; - string extension = Path.GetExtension(name); + + string extension = Path.GetExtension(name).Substring(1).ToLowerInvariant(); var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); fs.AddFile(fileName, fileStream); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a915caf4e4..2af4f04820 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -139,7 +139,7 @@ - + diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index 854abd2d77..481b9b7cb0 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -57,7 +57,7 @@ namespace umbraco.cms.businesslogic.datatype // handle upload if (name != String.Empty) { - var numberedFolder = MediaSubFolders.Current.Increment(); + var numberedFolder = MediaSubfolderCounter.Current.Increment(); string fileName = UmbracoSettings.UploadAllowDirectories ? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), name) : numberedFolder + "-" + name; diff --git a/src/umbraco.cms/businesslogic/media/UmbracoImageMediaFactory.cs b/src/umbraco.cms/businesslogic/media/UmbracoImageMediaFactory.cs index 3c77e0cb5c..e4bd16d704 100644 --- a/src/umbraco.cms/businesslogic/media/UmbracoImageMediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/UmbracoImageMediaFactory.cs @@ -1,15 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Web; -using Umbraco.Core.Logging; -using umbraco.BasePages; +using System.Collections.Generic; +using Umbraco.Core.Models; using umbraco.BusinessLogic; -using umbraco.cms.businesslogic.datatype; namespace umbraco.cms.businesslogic.media { @@ -27,146 +18,17 @@ namespace umbraco.cms.businesslogic.media public override void DoHandleMedia(Media media, PostedMediaFile postedFile, User user) { - // Get Image object, width and height - var image = Image.FromStream(postedFile.InputStream); - var fileWidth = image.Width; - var fileHeight = image.Height; + // Set media property to upload the file as well as set all related properties + media.MediaItem.SetValue("umbracoFile", postedFile.FileName, postedFile.InputStream); - // Get umbracoFile property - var propertyId = media.getProperty("umbracoFile").Id; + // Copy back the values from the internal IMedia to ensure that the values are persisted when saved + foreach (var property in media.MediaItem.Properties) + { + media.getProperty(property.Alias).Value = property.Value; + } - // Get paths - var destFilePath = FileSystem.GetRelativePath(propertyId, postedFile.FileName); - var ext = Path.GetExtension(destFilePath).Substring(1); - - // Set media properties - media.getProperty("umbracoFile").Value = FileSystem.GetUrl(destFilePath); - - if (media.getProperty("umbracoWidth") != null) - media.getProperty("umbracoWidth").Value = fileWidth; - - if (media.getProperty("umbracoHeight") != null) - media.getProperty("umbracoHeight").Value = fileHeight; - - if (media.getProperty("umbracoBytes") != null) - media.getProperty("umbracoBytes").Value = postedFile.ContentLength; - - if (media.getProperty("umbracoExtension") != null) - media.getProperty("umbracoExtension").Value = ext; - - if (media.getProperty("umbracoExtensio") != null) - media.getProperty("umbracoExtensio").Value = ext; - - // Generate thumbnail - var thumbDestFilePath = Path.Combine(Path.GetDirectoryName(destFilePath), Path.GetFileNameWithoutExtension(destFilePath) + "_thumb"); - GenerateThumbnail(image, 100, fileWidth, fileHeight, ext, thumbDestFilePath + ".jpg"); - - // Generate additional thumbnails based on PreValues set in DataTypeDefinition uploadField - GenerateAdditionalThumbnails(image, fileWidth, fileHeight, ext, thumbDestFilePath); - - image.Dispose(); - - FileSystem.AddFile(destFilePath, postedFile.InputStream, postedFile.ReplaceExisting); - - // Save media + // Save media (using legacy media object to ensure the usage of the legacy events). media.Save(); } - - private void GenerateAdditionalThumbnails(Image image, int fileWidth, int fileHeight, string ext, string destFilePath) - { - var uploadFieldDataTypeId = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"); - - DataTypeDefinition dataTypeDef = null; - - try - { - // Get DataTypeDefinition of upload field - dataTypeDef = DataTypeDefinition.GetByDataTypeId(uploadFieldDataTypeId); - } - catch (Exception e) - { - LogHelper.Error("Could get Upload Field datatype definition", e); - } - - if (dataTypeDef != null) - { - // Get PreValues - var preValues = PreValues.GetPreValues(dataTypeDef.Id); - - var thumbnails = ""; - if (preValues.Count > 0) - thumbnails = ((PreValue)preValues[0]).Value; - - if (thumbnails != "") - { - var thumbnailSizes = thumbnails.Split(";".ToCharArray()); - foreach (var thumb in thumbnailSizes.Where(thumb => thumb != "")) - { - GenerateThumbnail(image, int.Parse(thumb), fileWidth, fileHeight, ext, destFilePath + "_" + thumb + ".jpg"); - } - } - } - } - - private void GenerateThumbnail(Image image, int maxWidthHeight, int fileWidth, int fileHeight, string ext, string thumbnailFileName) - { - // Generate thumbnailee - var fx = (float)fileWidth / maxWidthHeight; - var fy = (float)fileHeight / maxWidthHeight; - - // must fit in thumbnail size - var f = Math.Max(fx, fy); //if (f < 1) f = 1; - var widthTh = (int)Math.Round(fileWidth / f); - var heightTh = (int)Math.Round(fileHeight / f); - - // fixes for empty width or height - if (widthTh == 0) - widthTh = 1; - - if (heightTh == 0) - heightTh = 1; - - // Create new image with best quality settings - var bp = new Bitmap(widthTh, heightTh); - var g = Graphics.FromImage(bp); - g.SmoothingMode = SmoothingMode.HighQuality; - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // Copy the old image to the new and resized - var rect = new Rectangle(0, 0, widthTh, heightTh); - g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); - - // Copy metadata - var codecs = ImageCodecInfo.GetImageEncoders(); - - var codec = ext.ToLower() == "png" || ext.ToLower() == "gif" - ? codecs.Single(t => t.MimeType.Equals("image/png")) - : codecs.Single(t => t.MimeType.Equals("image/jpeg")); - - // Set compresion ratio to 90% - var ep = new EncoderParameters(); - ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L); - - // Save the new image - if (codec != null) - { - var ms = new MemoryStream(); - bp.Save(ms, codec, ep); - ms.Seek(0, 0); - - FileSystem.AddFile(thumbnailFileName, ms); - - ms.Close(); - } - else - { - // Log error - LogHelper.Warn("Multiple file upload: Can't find appropriate codec"); - } - - bp.Dispose(); - g.Dispose(); - } } } From e0968904003a3471f509740fc2b93f8189b67cde Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Tue, 19 Feb 2013 20:12:13 +0600 Subject: [PATCH 3/4] Fixes: #U4-1537 --- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 14 ++++++-------- src/Umbraco.Web/Mvc/SurfaceController.cs | 13 ++++++++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index 43d7416a23..da6d761745 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -173,8 +173,7 @@ namespace Umbraco.Web.Mvc /// /// /// - /// The original route definition that would normally be used to route if it were not a POST - private IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo, RouteDefinition routeDefinition) + private IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo) { //set the standard route values/tokens requestContext.RouteData.Values["controller"] = postedInfo.ControllerName; @@ -210,9 +209,6 @@ namespace Umbraco.Web.Mvc } - //store the original route definition - requestContext.RouteData.DataTokens["umbraco-route-def"] = routeDefinition; - return handler; } @@ -277,7 +273,9 @@ namespace Umbraco.Web.Mvc } } - + + //store the route definition + requestContext.RouteData.DataTokens["umbraco-route-def"] = def; return def; } @@ -290,12 +288,12 @@ namespace Umbraco.Web.Mvc internal IHttpHandler GetHandlerForRoute(RequestContext requestContext, PublishedContentRequest publishedContentRequest) { var routeDef = GetUmbracoRouteDefinition(requestContext, publishedContentRequest); - + //Need to check for a special case if there is form data being posted back to an Umbraco URL var postedInfo = GetPostedFormInfo(requestContext); if (postedInfo != null) { - return HandlePostedValues(requestContext, postedInfo, routeDef); + return HandlePostedValues(requestContext, postedInfo); } //here we need to check if there is no hijacked route and no template assigned, if this is the case diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index c114b286dc..463162694f 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Web.Mvc; +using System.Web.Routing; using Umbraco.Core.Models; using Umbraco.Core; @@ -76,10 +77,16 @@ namespace Umbraco.Web.Mvc { get { - if (!ControllerContext.RouteData.DataTokens.ContainsKey("umbraco-route-def")) - throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name + " in the context of an Http POST when using the BeginUmbracoForm helper"); + var routeData = ControllerContext.IsChildAction + ? ControllerContext.ParentActionViewContext.RouteData + : ControllerContext.RouteData; - var routeDef = (RouteDefinition)ControllerContext.RouteData.DataTokens["umbraco-route-def"]; + if (!routeData.DataTokens.ContainsKey("umbraco-route-def")) + { + throw new InvalidOperationException("Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request"); + } + + var routeDef = (RouteDefinition)routeData.DataTokens["umbraco-route-def"]; return routeDef.PublishedContentRequest.PublishedContent; } } From c2d0e255dff18ab131106ce32281f4c77515800d Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Tue, 19 Feb 2013 20:17:17 +0600 Subject: [PATCH 4/4] Fixes: #U4-1537 --- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 14 ++++++-------- src/Umbraco.Web/Mvc/SurfaceController.cs | 13 ++++++++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index bba31be513..87a568fcca 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -173,8 +173,7 @@ namespace Umbraco.Web.Mvc /// /// /// - /// The original route definition that would normally be used to route if it were not a POST - private IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo, RouteDefinition routeDefinition) + private IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo) { //set the standard route values/tokens requestContext.RouteData.Values["controller"] = postedInfo.ControllerName; @@ -210,9 +209,6 @@ namespace Umbraco.Web.Mvc } - //store the original route definition - requestContext.RouteData.DataTokens["umbraco-route-def"] = routeDefinition; - return handler; } @@ -277,7 +273,9 @@ namespace Umbraco.Web.Mvc } } - + + //store the route definition + requestContext.RouteData.DataTokens["umbraco-route-def"] = def; return def; } @@ -290,12 +288,12 @@ namespace Umbraco.Web.Mvc internal IHttpHandler GetHandlerForRoute(RequestContext requestContext, PublishedContentRequest publishedContentRequest) { var routeDef = GetUmbracoRouteDefinition(requestContext, publishedContentRequest); - + //Need to check for a special case if there is form data being posted back to an Umbraco URL var postedInfo = GetPostedFormInfo(requestContext); if (postedInfo != null) { - return HandlePostedValues(requestContext, postedInfo, routeDef); + return HandlePostedValues(requestContext, postedInfo); } //here we need to check if there is no hijacked route and no template assigned, if this is the case diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index c114b286dc..463162694f 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Web.Mvc; +using System.Web.Routing; using Umbraco.Core.Models; using Umbraco.Core; @@ -76,10 +77,16 @@ namespace Umbraco.Web.Mvc { get { - if (!ControllerContext.RouteData.DataTokens.ContainsKey("umbraco-route-def")) - throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name + " in the context of an Http POST when using the BeginUmbracoForm helper"); + var routeData = ControllerContext.IsChildAction + ? ControllerContext.ParentActionViewContext.RouteData + : ControllerContext.RouteData; - var routeDef = (RouteDefinition)ControllerContext.RouteData.DataTokens["umbraco-route-def"]; + if (!routeData.DataTokens.ContainsKey("umbraco-route-def")) + { + throw new InvalidOperationException("Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request"); + } + + var routeDef = (RouteDefinition)routeData.DataTokens["umbraco-route-def"]; return routeDef.PublishedContentRequest.PublishedContent; } }