diff --git a/src/Umbraco.Core/Models/PartialView.cs b/src/Umbraco.Core/Models/PartialView.cs
index 4ec7cf567d..f963ff0e1a 100644
--- a/src/Umbraco.Core/Models/PartialView.cs
+++ b/src/Umbraco.Core/Models/PartialView.cs
@@ -28,10 +28,18 @@ namespace Umbraco.Core.Models
/// True if file is valid, otherwise false
public override bool IsValid()
{
- //Validate extension
- return IOHelper.VerifyFileExtension(Path, new List { "cshtml" });
+ //TODO: Validate using the macro engine
+ //var engine = MacroEngineFactory.GetEngine(PartialViewMacroEngine.EngineName);
+ //engine.Validate(...)
+
+ var validatePath = IOHelper.ValidateEditPath(IOHelper.MapPath(Path), BasePath);
+ var verifyFileExtension = IOHelper.VerifyFileExtension(Path, new List { "cshtml" });
+
+ return validatePath && verifyFileExtension;
}
+ public string OldFileName { get; set; }
+
public string FileName { get; set; }
public string SnippetName { get; set; }
@@ -48,8 +56,6 @@ namespace Umbraco.Core.Models
public string ReturnUrl { get; set; }
- public bool SaveSucceeded { get; set; }
-
internal Regex HeaderMatch
{
get { return _headerMatch; }
diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs
index 40389b865e..90a7c7061c 100644
--- a/src/Umbraco.Core/Services/FileService.cs
+++ b/src/Umbraco.Core/Services/FileService.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Web;
using Umbraco.Core.Auditing;
@@ -367,24 +368,25 @@ namespace Umbraco.Core.Services
return template.IsValid();
}
- internal PartialView CreatePartialView(PartialView partialView)
+ internal Attempt CreatePartialView(PartialView partialView)
{
var partialViewsFileSystem = new PhysicalFileSystem(partialView.BasePath);
var relativeFilePath = partialView.ParentFolderName.EnsureEndsWith('/') + partialViewsFileSystem.GetRelativePath(partialView.FileName);
+ partialView.ReturnUrl = string.Format(partialView.EditViewFile + "?file={0}", HttpUtility.UrlEncode(relativeFilePath));
//return the link to edit the file if it already exists
if (partialViewsFileSystem.FileExists(partialView.Path))
- {
- partialView.ReturnUrl = string.Format(partialView.EditViewFile + "?file={0}", HttpUtility.UrlEncode(relativeFilePath));
- partialView.SaveSucceeded = true;
- return partialView;
- }
+ return Attempt.Succeed(partialView);
if (CreatingPartialView.IsRaisedEventCancelled(new NewEventArgs(partialView, true, partialView.Alias, -1), this))
{
- LogHelper.Info(string.Format("Creating Partial View {0} was cancelled by an event handler.", partialViewsFileSystem.GetFullPath(partialView.FileName)));
- partialView.SaveSucceeded = false;
- return partialView;
+ // We have nowhere to return to, clear ReturnUrl
+ partialView.ReturnUrl = string.Empty;
+
+ var failureMessage = string.Format("Creating Partial View {0} was cancelled by an event handler.", partialViewsFileSystem.GetFullPath(partialView.FileName));
+ LogHelper.Info(failureMessage);
+
+ return Attempt.Fail(partialView, new ArgumentException(failureMessage));
}
//create the file
@@ -411,12 +413,10 @@ namespace Umbraco.Core.Services
if (partialView.CreateMacro)
CreatePartialViewMacro(partialView);
-
- partialView.ReturnUrl = string.Format(partialView.EditViewFile + "?file={0}", HttpUtility.UrlEncode(relativeFilePath));
CreatedPartialView.RaiseEvent(new NewEventArgs(partialView, false, partialView.Alias, -1), this);
- return partialView;
+ return Attempt.Succeed(partialView);
}
internal static void CreatePartialViewMacro(PartialView partialView)
@@ -459,6 +459,46 @@ namespace Umbraco.Core.Services
return true;
}
+ internal Attempt SavePartialView(PartialView partialView, int userId = 0)
+ {
+ if (SavingPartialView.IsRaisedEventCancelled(new SaveEventArgs(partialView, true), this))
+ {
+ return Attempt.Fail(new ArgumentException("Save was cancelled by an event handler " + partialView.FileName));
+ }
+
+ //Directory check.. only allow files in script dir and below to be edited
+ if (partialView.IsValid() == false)
+ {
+ return Attempt.Fail(
+ new ArgumentException(string.Format("Illegal path: {0} or illegal file extension {1}",
+ partialView.Path,
+ partialView.FileName.Substring(partialView.FileName.LastIndexOf(".", StringComparison.Ordinal)))));
+ }
+
+ //NOTE: I've left the below here just for informational purposes. If we save a file this way, then the UTF8
+ // BOM mucks everything up, strangely, if we use WriteAllText everything is ok!
+ // http://issues.umbraco.org/issue/U4-2118
+ //using (var sw = System.IO.File.CreateText(savePath))
+ //{
+ // sw.Write(val);
+ //}
+
+ System.IO.File.WriteAllText(partialView.Path, partialView.Content, Encoding.UTF8);
+
+ //deletes the old file
+ if (partialView.FileName != partialView.OldFileName)
+ {
+ // Create a new PartialView class so that we can set the FileName of the file that needs deleting
+ var deletePartial = partialView;
+ deletePartial.FileName = partialView.OldFileName;
+ DeletePartialView(deletePartial, userId);
+ }
+
+ SavedPartialView.RaiseEvent(new SaveEventArgs(partialView), this);
+
+ return Attempt.Succeed(partialView);
+ }
+
//TODO Method to change name and/or alias of view/masterpage template
#region Event Handlers
@@ -522,6 +562,16 @@ namespace Umbraco.Core.Services
///
public static event TypedEventHandler> SavedStylesheet;
+ ///
+ /// Occurs before Save
+ ///
+ internal static event TypedEventHandler> SavingPartialView;
+
+ ///
+ /// Occurs after Save
+ ///
+ internal static event TypedEventHandler> SavedPartialView;
+
///
/// Occurs before Create
///
@@ -543,5 +593,6 @@ namespace Umbraco.Core.Services
internal static event TypedEventHandler> DeletedPartialView;
#endregion
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs
index 17af82353d..56f52887ce 100644
--- a/src/Umbraco.Web/WebServices/SaveFileController.cs
+++ b/src/Umbraco.Web/WebServices/SaveFileController.cs
@@ -5,6 +5,7 @@ using System.Web.Mvc;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
+using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Macros;
using Umbraco.Web.Mvc;
@@ -38,57 +39,27 @@ namespace Umbraco.Web.WebServices
public JsonResult SavePartialView(string filename, string oldName, string contents)
{
var folderPath = SystemDirectories.MvcViews.EnsureEndsWith('/');// +"/Partials/";
-
- // validate file
- IOHelper.ValidateEditPath(IOHelper.MapPath(folderPath + filename), folderPath);
- // validate extension
- IOHelper.ValidateFileExtension(IOHelper.MapPath(folderPath + filename), new[] { "cshtml" }.ToList());
-
- //TODO: Validate using the macro engine
- var engine = MacroEngineFactory.GetEngine(PartialViewMacroEngine.EngineName);
- //engine.Validate(...)
-
- var val = contents;
- var saveOldPath = oldName.StartsWith("~/") ? IOHelper.MapPath(oldName) : IOHelper.MapPath(folderPath + oldName);
var savePath = filename.StartsWith("~/") ? IOHelper.MapPath(filename) : IOHelper.MapPath(folderPath + filename);
- //Directory check.. only allow files in script dir and below to be edited
- if (!savePath.StartsWith(IOHelper.MapPath(folderPath)))
+ var partialView = new PartialView(savePath)
+ {
+ BasePath = folderPath,
+ OldFileName = oldName,
+ FileName = filename,
+ Content = contents,
+ };
+
+ var fileService = new FileService();
+ var attempt = fileService.SavePartialView(partialView);
+
+ if (attempt.Success == false)
{
return Failed(
ui.Text("speechBubbles", "partialViewErrorText"), ui.Text("speechBubbles", "partialViewErrorHeader"),
//pass in a new exception ... this will also append the the message
- new ArgumentException("Illegal path: " + savePath));
+ attempt.Exception);
}
-
- if (Saving.IsRaisedEventCancelled(new SaveEventArgs(savePath), this))
- {
- return Failed(
- ui.Text("speechBubbles", "partialViewErrorText"), ui.Text("speechBubbles", "partialViewErrorHeader"),
- //pass in a new exception ... this will also append the the message
- new ArgumentException("Save was cancelled by an event handler " + savePath));
- }
-
- //deletes the old file
- if (savePath != saveOldPath)
- {
- if (System.IO.File.Exists(saveOldPath))
- System.IO.File.Delete(saveOldPath);
- }
-
- //NOTE: I've left the below here just for informational purposes. If we save a file this way, then the UTF8
- // BOM mucks everything up, strangely, if we use WriteAllText everything is ok!
- // http://issues.umbraco.org/issue/U4-2118
- //using (var sw = System.IO.File.CreateText(savePath))
- //{
- // sw.Write(val);
- //}
-
- System.IO.File.WriteAllText(savePath, val, Encoding.UTF8);
-
- Saved.RaiseEvent(new SaveEventArgs(savePath, false), this);
-
return Success(ui.Text("speechBubbles", "partialViewSavedText"), ui.Text("speechBubbles", "partialViewSavedHeader"));
}
@@ -185,15 +156,5 @@ namespace Umbraco.Web.WebServices
message = message + (exception == null ? "" : (exception.Message + ". Check log for details."))
});
}
-
- ///
- /// Occurs before Create
- ///
- internal static event TypedEventHandler> Saving;
-
- ///
- /// Occurs after Create
- ///
- internal static event TypedEventHandler> Saved;
}
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs
index 0039f293c6..fdceb238d3 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs
@@ -65,11 +65,11 @@ namespace umbraco
};
var fileService = new FileService();
- var partialView = fileService.CreatePartialView(model);
+ var attempt = fileService.CreatePartialView(model);
- _returnUrl = partialView.ReturnUrl;
+ _returnUrl = attempt.Result.ReturnUrl;
- return partialView.SaveSucceeded;
+ return attempt.Success;
}
public override bool PerformDelete()