added umbracoSettings.scripting.razor.dataTypeModelStaticMappings to allow RazorDataTypeModels to be specified in the umbracoSettings.config file. These static mappings override the dynamic mappings provided by the RazorDataTypeModel attribute, including priority (from previous commit). You can use this feature to force a particular data type [optionally on a specific document type and/or property] to use a specific model, or exclude the data type guid and just use the aliases. This feature is inteded to be used when you want to force a particular type to return as Integer. See next commit for detail about the Type Names to use.

This commit is contained in:
agrath
2012-01-09 12:38:22 -13:00
parent 6eae64eaf3
commit e6f0c2a17c
5 changed files with 185 additions and 35 deletions

View File

@@ -135,6 +135,16 @@
<element>ul</element>
<element>span</element>
</notDynamicXmlDocumentElements>
<dataTypeModelStaticMappings>
<!--
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping documentTypeAlias="textPage" nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000" documentTypeAlias="textPage" nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000" documentTypeAlias="textPage">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000" nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
-->
</dataTypeModelStaticMappings>
</razor>
</scripting>

View File

@@ -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<System.Tuple<Guid, int>, 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

View File

@@ -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)
);
}
}
}

View File

@@ -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<RazorDataTypeModelStaticMappingItem> 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<RazorDataTypeModelStaticMappingItem>;
}
/*
<dataTypeModelStaticMappings>
<mapping dataTypeGuid="ef94c406-9e83-4058-a780-0375624ba7ca">DigibizAdvancedMediaPicker.RazorModel.ModelBinder</mapping>
<mapping documentTypeAlias="RoomPage" nodeTypeAlias="teaser">DigibizAdvancedMediaPicker.RazorModel.ModelBinder</mapping>
</dataTypeModelStaticMappings>
*/
List<RazorDataTypeModelStaticMappingItem> items = new List<RazorDataTypeModelStaticMappingItem>();
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;
}
}
/// <summary>
/// Gets a value indicating whether umbraco will clone XML cache on publish.
/// </summary>
@@ -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;
}

View File

@@ -170,6 +170,7 @@
<Compile Include="MenuItemI.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Razor\RazorDataTypeModelStaticMappingItem.cs" />
<Compile Include="StateHelper.cs" />
<Compile Include="ui.cs">
<SubType>Code</SubType>