diff --git a/config templates/config/umbracoSettings.config b/config templates/config/umbracoSettings.config index 555ed2317d..95c4fcca14 100644 --- a/config templates/config/umbracoSettings.config +++ b/config templates/config/umbracoSettings.config @@ -135,6 +135,16 @@ ul span + + + diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs index a3112c995f..9aad2b231b 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs @@ -461,50 +461,58 @@ namespace umbraco.MacroEngines RazorDataTypeModelTypes = null; } } - HttpContext.Current.Trace.Write(string.Format("Checking the RazorDataTypeModelTypes cache to see if the GUID {0} has a Model...", dataType)); + HttpContext.Current.Trace.Write(string.Format("Checking for a RazorDataTypeModel for data type guid {0}...", dataType)); + HttpContext.Current.Trace.Write("Checking the RazorDataTypeModelTypes static mappings to see if there is a static mapping..."); + + RazorDataTypeModelStaticMappingItem staticMapping = UmbracoSettings.RazorDataTypeModelStaticMapping.FirstOrDefault(mapping => + { + return mapping.Applies(dataType, data.ContextAlias, data.Alias); + }); + if (staticMapping != null) + { + HttpContext.Current.Trace.Write(string.Format("Found a staticMapping defined {0}, instantiating type and attempting to apply model...", staticMapping.Raw)); + Type dataTypeType = Type.GetType(staticMapping.TypeName); + if (dataTypeType != null) + { + object instance = null; + if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, data.Value, out instance)) + { + result = instance; + return true; + } + else + { + HttpContext.Current.Trace.Write("Failed"); + HttpContext.Current.Trace.Warn(string.Format("Failed to create the instance of the model binder")); + } + } + else + { + HttpContext.Current.Trace.Warn(string.Format("staticMapping type name {0} came back as null from Type.GetType; check the casing, assembly presence, assembly framework version, namespace", staticMapping.TypeName)); + } + } + else + { + HttpContext.Current.Trace.Write(string.Format("There isn't a staticMapping defined so checking the RazorDataTypeModelTypes cache...")); + } + + if (RazorDataTypeModelTypes != null && RazorDataTypeModelTypes.Where(model => model.Key.Item1 == dataType).Any() && dataType != Guid.Empty) { var razorDataTypeModelDefinition = RazorDataTypeModelTypes.Where(model => model.Key.Item1 == dataType).OrderByDescending(model => model.Key.Item2).FirstOrDefault(); if (!(razorDataTypeModelDefinition.Equals(default(KeyValuePair, Type>)))) { Type dataTypeType = razorDataTypeModelDefinition.Value; - HttpContext.Current.Trace.Write(string.Format("Found dataType {0} for GUID {1}", dataTypeType.FullName, dataType)); - IRazorDataTypeModel razorDataTypeModel = Activator.CreateInstance(dataTypeType, false) as IRazorDataTypeModel; - HttpContext.Current.Trace.Write(string.Format("Instantiating {0}...", dataTypeType.FullName)); - if (razorDataTypeModel != null) + object instance = null; + if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, data.Value, out instance)) { - HttpContext.Current.Trace.Write("Success"); - object instance = null; - HttpContext.Current.Trace.Write("Calling Init on razorDataTypeModel"); - if (razorDataTypeModel.Init(n.Id, data.Value, out instance)) - { - if (instance != null) - { - HttpContext.Current.Trace.Write(string.Format("razorDataTypeModel successfully instantiated and returned a valid instance of type {0}", instance.GetType().FullName)); - } - else - { - HttpContext.Current.Trace.Warn("razorDataTypeModel successfully instantiated but returned null for instance"); - } - result = instance; - return true; - } - else - { - if (instance != null) - { - HttpContext.Current.Trace.Write(string.Format("razorDataTypeModel returned false but returned a valid instance of type {0}", instance.GetType().FullName)); - } - else - { - HttpContext.Current.Trace.Warn("razorDataTypeModel successfully instantiated but returned null for instance"); - } - } + result = instance; + return true; } else { HttpContext.Current.Trace.Write("Failed"); - HttpContext.Current.Trace.Warn(string.Format("DataTypeModel {0} failed to instantiate, perhaps it is lacking a parameterless constructor or doesn't implement IRazorDataTypeModel?", dataTypeType.FullName)); + HttpContext.Current.Trace.Warn(string.Format("Failed to create the instance of the model binder")); } } else @@ -587,7 +595,49 @@ namespace umbraco.MacroEngines } return true; } - + private bool TryCreateInstanceRazorDataTypeModel(Guid dataType, Type dataTypeType, string value, out object result) + { + HttpContext.Current.Trace.Write(string.Format("Found dataType {0} for GUID {1}", dataTypeType.FullName, dataType)); + IRazorDataTypeModel razorDataTypeModel = Activator.CreateInstance(dataTypeType, false) as IRazorDataTypeModel; + HttpContext.Current.Trace.Write(string.Format("Instantiating {0}...", dataTypeType.FullName)); + if (razorDataTypeModel != null) + { + HttpContext.Current.Trace.Write("Success"); + object instance = null; + HttpContext.Current.Trace.Write("Calling Init on razorDataTypeModel"); + if (razorDataTypeModel.Init(n.Id, value, out instance)) + { + if (instance != null) + { + HttpContext.Current.Trace.Write(string.Format("razorDataTypeModel successfully instantiated and returned a valid instance of type {0}", instance.GetType().FullName)); + } + else + { + HttpContext.Current.Trace.Warn("razorDataTypeModel successfully instantiated but returned null for instance"); + } + result = instance; + return true; + } + else + { + if (instance != null) + { + HttpContext.Current.Trace.Write(string.Format("razorDataTypeModel returned false but returned a valid instance of type {0}", instance.GetType().FullName)); + } + else + { + HttpContext.Current.Trace.Warn("razorDataTypeModel successfully instantiated but returned null for instance"); + } + } + } + else + { + HttpContext.Current.Trace.Write("Failed"); + HttpContext.Current.Trace.Warn(string.Format("DataTypeModel {0} failed to instantiate, perhaps it is lacking a parameterless constructor or doesn't implement IRazorDataTypeModel?", dataTypeType.FullName)); + } + result = null; + return false; + } private bool ConvertPropertyValueByDataType(ref object result, string name, Guid dataType) { //the resulting property is a string, but to support some of the nice linq stuff in .Where diff --git a/umbraco/businesslogic/Razor/RazorDataTypeModelStaticMappingItem.cs b/umbraco/businesslogic/Razor/RazorDataTypeModelStaticMappingItem.cs new file mode 100644 index 0000000000..2bd9cce16b --- /dev/null +++ b/umbraco/businesslogic/Razor/RazorDataTypeModelStaticMappingItem.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace umbraco.MacroEngines +{ + public class RazorDataTypeModelStaticMappingItem + { + public string Raw; + + //if all of the set (non null) properties match the property data currently being evaluated + public string PropertyTypeAlias; + public string NodeTypeAlias; + public Guid? DataTypeGuid; + + public string TypeName; + + public RazorDataTypeModelStaticMappingItem() { } + + public bool Applies(Guid dataTypeGuid, string nodeTypeAlias, string propertyTypeAlias) + { + return + ( + (this.NodeTypeAlias != null || this.PropertyTypeAlias != null || this.DataTypeGuid != null) && + ((this.DataTypeGuid != null && this.DataTypeGuid == dataTypeGuid) || this.DataTypeGuid == null) && + ((this.PropertyTypeAlias != null && this.PropertyTypeAlias == propertyTypeAlias) || this.PropertyTypeAlias == null) && + ((this.NodeTypeAlias != null && this.NodeTypeAlias == nodeTypeAlias) || this.NodeTypeAlias == null) + ); + } + } +} diff --git a/umbraco/businesslogic/UmbracoSettings.cs b/umbraco/businesslogic/UmbracoSettings.cs index 4d5aa286f1..4b275c77d4 100644 --- a/umbraco/businesslogic/UmbracoSettings.cs +++ b/umbraco/businesslogic/UmbracoSettings.cs @@ -6,6 +6,7 @@ using System.Web.Caching; using System.Xml; using umbraco.BusinessLogic; using System.Collections.Generic; +using umbraco.MacroEngines; namespace umbraco { @@ -415,6 +416,62 @@ namespace umbraco } } + public static List RazorDataTypeModelStaticMapping + { + get + { + if (HttpContext.Current != null && HttpContext.Current.Cache != null && HttpContext.Current.Cache["settings.scripting.razor.dataTypeModelStaticMappings"] != null) + { + return HttpContext.Current.Cache["settings.scripting.razor.dataTypeModelStaticMappings"] as List; + } + /* + + DigibizAdvancedMediaPicker.RazorModel.ModelBinder + DigibizAdvancedMediaPicker.RazorModel.ModelBinder + + */ + List items = new List(); + XmlNode root = GetKeyAsNode("/settings/scripting/razor/dataTypeModelStaticMappings"); + if (root != null) + { + foreach (XmlNode element in root.SelectNodes(".//mapping")) + { + string propertyTypeAlias = null, nodeTypeAlias = null; + Guid? dataTypeGuid = null; + if (!string.IsNullOrEmpty(element.InnerText)) + { + if (element.Attributes["dataTypeGuid"] != null) + { + dataTypeGuid = (Guid?)new Guid(element.Attributes["dataTypeGuid"].Value); + } + if (element.Attributes["propertyTypeAlias"] != null && !string.IsNullOrEmpty(element.Attributes["propertyTypeAlias"].Value)) + { + propertyTypeAlias = element.Attributes["propertyTypeAlias"].Value; + } + if (element.Attributes["nodeTypeAlias"] != null && !string.IsNullOrEmpty(element.Attributes["nodeTypeAlias"].Value)) + { + nodeTypeAlias = element.Attributes["nodeTypeAlias"].Value; + } + items.Add(new RazorDataTypeModelStaticMappingItem() + { + DataTypeGuid = dataTypeGuid, + PropertyTypeAlias = propertyTypeAlias, + NodeTypeAlias = nodeTypeAlias, + TypeName = element.InnerText, + Raw = element.OuterXml + }); + } + } + } + if (HttpContext.Current != null && HttpContext.Current.Cache != null) + { + HttpContext.Current.Cache.Add("settings.scripting.razor.dataTypeModelStaticMappings", items, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 20, 0), CacheItemPriority.AboveNormal, null); + } + return items; + + } + } + /// /// Gets a value indicating whether umbraco will clone XML cache on publish. /// @@ -984,7 +1041,7 @@ namespace umbraco { Trace.WriteLine("Could not load /settings/content/ResolveUrlsFromTextString from umbracosettings.config:\r\n {0}", ex.Message); - + // set url resolving to true (default (legacy) behavior) to ensure we don't keep writing to trace _resolveUrlsFromTextString = true; } diff --git a/umbraco/businesslogic/umbraco.businesslogic.csproj b/umbraco/businesslogic/umbraco.businesslogic.csproj index b5fa02dea9..e51a7ae406 100644 --- a/umbraco/businesslogic/umbraco.businesslogic.csproj +++ b/umbraco/businesslogic/umbraco.businesslogic.csproj @@ -170,6 +170,7 @@ Code + Code