diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs
index 6828b0e353..e70046c90e 100644
--- a/src/Umbraco.Core/IO/SystemDirectories.cs
+++ b/src/Umbraco.Core/IO/SystemDirectories.cs
@@ -69,6 +69,15 @@ namespace Umbraco.Core.IO
}
}
+ public static string AppPlugins
+ {
+ get
+ {
+ //NOTE: this is not configurable and shouldn't need to be
+ return "~/App_Plugins";
+ }
+ }
+
public static string MvcViews
{
get
diff --git a/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs b/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs
index 3f2a0ec4ef..faa356e177 100644
--- a/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs
+++ b/src/Umbraco.Web.UI/umbraco/developer/Macros/EditMacro.aspx.cs
@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI.WebControls;
using Umbraco.Core.IO;
@@ -32,10 +33,11 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
{
base.PopulateFieldsOnLoad(macro, macroAssemblyValue, macroTypeValue);
//check if the ScriptingFile property contains the MacroPartials path
- if (macro.ScriptingFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/"))
+ if (macro.ScriptingFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
+ || (Regex.IsMatch(macro.ScriptingFile, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled)))
{
macroPython.Text = "";
- SelectedPartialView.Text = Path.GetFileName(macro.ScriptingFile);
+ SelectedPartialView.Text = macro.ScriptingFile;
}
}
@@ -52,7 +54,7 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
base.SetMacroValuesFromPostBack(macro, macroCachePeriod, macroAssemblyValue, macroTypeValue);
if (!SelectedPartialView.Text.IsNullOrWhiteSpace())
{
- macro.ScriptingFile = SystemDirectories.MvcViews + "/MacroPartials/" + SelectedPartialView.Text;
+ macro.ScriptingFile = SelectedPartialView.Text;
}
}
@@ -62,19 +64,40 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
private void PopulatePartialViewFiles()
{
var partialsDir = IOHelper.MapPath(SystemDirectories.MvcViews + "/MacroPartials");
- var views = GetPartialViewFiles(partialsDir, partialsDir);
- PartialViewList.DataSource = views;
+ //get all the partials in the normal /MacroPartials folder
+ var foundMacroPartials = GetPartialViewFiles(partialsDir, partialsDir, SystemDirectories.MvcViews + "/MacroPartials");
+ //now try to find all of them int he App_Plugins/[PackageName]/Views/MacroPartials folder
+ var partialPluginsDir = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins));
+ foreach(var d in partialPluginsDir.GetDirectories())
+ {
+ var viewsFolder = d.GetDirectories("Views");
+ if (viewsFolder.Any())
+ {
+ var macroPartials = viewsFolder.First().GetDirectories("MacroPartials");
+ if (macroPartials.Any())
+ {
+ foundMacroPartials = foundMacroPartials.Concat(
+ GetPartialViewFiles(macroPartials.First().FullName, macroPartials.First().FullName, SystemDirectories.AppPlugins + "/" + d.Name + "/Views/MacroPartials"));
+ }
+ }
+ }
+
+
+
+ PartialViewList.DataSource = foundMacroPartials;
PartialViewList.DataBind();
PartialViewList.Items.Insert(0, new ListItem("Browse partial view files on server...", string.Empty));
}
///
- /// Get the list of partial view files in the ~/Views/MacroPartials folder
+ /// Get the list of partial view files in the ~/Views/MacroPartials folder and in all
+ /// folders of ~/App_Plugins/[PackageName]/Views/MacroPartials
///
///
///
+ ///
///
- private IEnumerable GetPartialViewFiles(string orgPath, string path)
+ private IEnumerable GetPartialViewFiles(string orgPath, string path, string prefixVirtualPath)
{
var files = new List();
var dirInfo = new DirectoryInfo(path);
@@ -83,12 +106,14 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
var dirInfos = dirInfo.GetDirectories();
foreach (var dir in dirInfos)
{
- files.AddRange(GetPartialViewFiles(orgPath, path + "/" + dir.Name));
+ files.AddRange(GetPartialViewFiles(orgPath, path + "/" + dir.Name, prefixVirtualPath));
}
var fileInfo = dirInfo.GetFiles("*.*");
- files.AddRange(fileInfo.Select(file => (path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/')));
+ files.AddRange(
+ fileInfo.Select(file =>
+ prefixVirtualPath.TrimEnd('/') + "/" + (path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/')));
return files;
}
diff --git a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs
index 600d2d1fd6..28e558e358 100644
--- a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs
+++ b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
@@ -90,7 +91,8 @@ namespace Umbraco.Web.Macros
if (macro == null) throw new ArgumentNullException("macro");
if (currentPage == null) throw new ArgumentNullException("currentPage");
- if (!macro.ScriptName.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/"))
+ if (!macro.ScriptName.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
+ && (!Regex.IsMatch(macro.ScriptName, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled)))
{
throw new InvalidOperationException("Cannot render the Partial View Macro with file: " + macro.ScriptName + ". All Partial View Macros must exist in the " + SystemDirectories.MvcViews + "/MacroPartials/ folder");
}
diff --git a/src/Umbraco.Web/Mvc/Constants.cs b/src/Umbraco.Web/Mvc/Constants.cs
index 63ddf5fa05..1ec35e4928 100644
--- a/src/Umbraco.Web/Mvc/Constants.cs
+++ b/src/Umbraco.Web/Mvc/Constants.cs
@@ -3,6 +3,5 @@ namespace Umbraco.Web.Mvc
internal static class Constants
{
public const string ViewLocation = "~/Views";
- public const string PluginsLocation = "~/App_Plugins";
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Mvc/PluginViewEngine.cs b/src/Umbraco.Web/Mvc/PluginViewEngine.cs
index bca14c2058..2ffc98afa2 100644
--- a/src/Umbraco.Web/Mvc/PluginViewEngine.cs
+++ b/src/Umbraco.Web/Mvc/PluginViewEngine.cs
@@ -33,16 +33,16 @@ namespace Umbraco.Web.Mvc
var viewLocationsArray = new[]
{
- string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.cshtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.vbhtml")
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.vbhtml")
};
//set all of the area view locations to the plugin folder
AreaViewLocationFormats = viewLocationsArray
.Concat(new[]
{
- string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.cshtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.vbhtml")
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.vbhtml")
})
.ToArray();
@@ -51,15 +51,15 @@ namespace Umbraco.Web.Mvc
AreaPartialViewLocationFormats = new[]
{
//will be used when we have partial view and child action macros
- string.Concat(Constants.PluginsLocation, "/{2}/Views/Partials/{0}.cshtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/Partials/{0}.vbhtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/MacroPartials/{0}.cshtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/MacroPartials/{0}.vbhtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.vbhtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.cshtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.vbhtml"),
//for partials
- string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.cshtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/{1}/{0}.vbhtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.cshtml"),
- string.Concat(Constants.PluginsLocation, "/{2}/Views/Shared/{0}.vbhtml")
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.vbhtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"),
+ string.Concat(SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.vbhtml")
};
}
diff --git a/src/umbraco.cms/businesslogic/macro/Macro.cs b/src/umbraco.cms/businesslogic/macro/Macro.cs
index 5c61562108..6fc80ec556 100644
--- a/src/umbraco.cms/businesslogic/macro/Macro.cs
+++ b/src/umbraco.cms/businesslogic/macro/Macro.cs
@@ -2,6 +2,7 @@ using System;
using System.Data;
using System.Security.Cryptography;
using System.Text;
+using System.Text.RegularExpressions;
using System.Xml;
using System.Runtime.CompilerServices;
using Umbraco.Core.IO;
@@ -536,9 +537,11 @@ namespace umbraco.cms.businesslogic.macro
{
//we need to check if the file path saved is a virtual path starting with ~/Views/MacroPartials, if so then this is
//a partial view macro, not a script macro
- return scriptFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
- ? MacroTypes.PartialView
- : MacroTypes.Script;
+ //we also check if the file exists in ~/App_Plugins/[Packagename]/Views/MacroPartials, if so then it is also a partial view.
+ return (scriptFile.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
+ || (Regex.IsMatch(scriptFile, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled)))
+ ? MacroTypes.PartialView
+ : MacroTypes.Script;
}
if (!string.IsNullOrEmpty(scriptType) && scriptType.ToLower().IndexOf(".ascx") > -1)