Fixes: U4-6210 ExtensionMethodFinder doesn't work with overloaded extensions - this means overloaded extension methods for dynamic content won't work. and finalizes: U4-6209 GetGridHtml needs to be an extension on HtmlHelper not IPublishedContent so that ViewData and ModelState are inherited
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
@@ -907,10 +908,12 @@ namespace Umbraco.Web.Dynamics
|
||||
//SD: I have yet to see extension methods actually being called in the dynamic parsing... need to unit test these
|
||||
// scenarios and figure out why all this type checking occurs.
|
||||
|
||||
var runtimeCache = ApplicationContext.Current != null ? ApplicationContext.Current.ApplicationCache.RuntimeCache : new NullCacheProvider();
|
||||
|
||||
if (type == typeof(string) && instanceAsString != null)
|
||||
{
|
||||
Expression[] newArgs = (new List<Expression>() { Expression.Invoke(instanceAsString, instanceExpression) }).Concat(args).ToArray();
|
||||
mb = ExtensionMethodFinder.FindExtensionMethod(typeof(string), newArgs, id, true);
|
||||
mb = ExtensionMethodFinder.FindExtensionMethod(runtimeCache, typeof(string), newArgs, id, true);
|
||||
if (mb != null)
|
||||
{
|
||||
return CallMethodOnDynamicNode(instance, newArgs, instanceAsString, instanceExpression, (MethodInfo)mb, true);
|
||||
@@ -919,7 +922,7 @@ namespace Umbraco.Web.Dynamics
|
||||
if (type == typeof(string) && instanceAsString == null && instance is MemberExpression)
|
||||
{
|
||||
Expression[] newArgs = (new List<Expression>() { instance }).Concat(args).ToArray();
|
||||
mb = ExtensionMethodFinder.FindExtensionMethod(typeof(string), newArgs, id, true);
|
||||
mb = ExtensionMethodFinder.FindExtensionMethod(runtimeCache, typeof(string), newArgs, id, true);
|
||||
if (mb != null)
|
||||
{
|
||||
return Expression.Call(null, (MethodInfo)mb, newArgs);
|
||||
@@ -994,7 +997,7 @@ namespace Umbraco.Web.Dynamics
|
||||
//e.g. uBlogsyPostDate.Date
|
||||
//SD: Removed the NonPublic accessor here because this will never work in medium trust, wondering why it is NonPublic vs Public ? Have changed to Public.
|
||||
//MethodInfo ReflectPropertyValue = this.GetType().GetMethod("ReflectPropertyValue", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
MethodInfo ReflectPropertyValue = this.GetType().GetMethod("ReflectPropertyValue", BindingFlags.Public | BindingFlags.Static);
|
||||
MethodInfo reflectPropertyValue = this.GetType().GetMethod("ReflectPropertyValue", BindingFlags.Public | BindingFlags.Static);
|
||||
ParameterExpression convertDynamicNullToBooleanFalse = Expression.Parameter(typeof(bool), "convertDynamicNullToBooleanFalse");
|
||||
ParameterExpression result = Expression.Parameter(typeof(object), "result");
|
||||
ParameterExpression idParam = Expression.Parameter(typeof(string), "id");
|
||||
@@ -1008,7 +1011,7 @@ namespace Umbraco.Web.Dynamics
|
||||
new[] { lambdaResult, result, idParam, convertDynamicNullToBooleanFalse },
|
||||
Expression.Assign(convertDynamicNullToBooleanFalse, Expression.Constant(_flagConvertDynamicNullToBooleanFalse, typeof(bool))),
|
||||
Expression.Assign(lambdaResult, Expression.Invoke(instance, lambdaInstanceExpression)),
|
||||
Expression.Assign(result, Expression.Call(ReflectPropertyValue, lambdaResult, Expression.Constant(id))),
|
||||
Expression.Assign(result, Expression.Call(reflectPropertyValue, lambdaResult, Expression.Constant(id))),
|
||||
Expression.IfThen(
|
||||
Expression.AndAlso(
|
||||
Expression.TypeEqual(result, typeof(DynamicNull)),
|
||||
|
||||
@@ -48,38 +48,30 @@ namespace Umbraco.Web
|
||||
var model = prop.Value;
|
||||
|
||||
var asString = model as string;
|
||||
if (asString.IsNullOrWhiteSpace()) return new MvcHtmlString(string.Empty);
|
||||
if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty);
|
||||
|
||||
return html.Partial(view, model);
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("This should not be used, GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedProperty property, string framework = "bootstrap3")
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedProperty property, HtmlHelper html, string framework = "bootstrap3")
|
||||
{
|
||||
var asString = property.Value as string;
|
||||
if (asString.IsNullOrWhiteSpace()) return new MvcHtmlString(string.Empty);
|
||||
|
||||
|
||||
var view = "Grid/" + framework;
|
||||
return new MvcHtmlString(RenderPartialViewToString(view, property.Value));
|
||||
return html.Partial(view, property.Value);
|
||||
}
|
||||
|
||||
[Obsolete("This should not be used, GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem)
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, HtmlHelper html)
|
||||
{
|
||||
return GetGridHtml(contentItem, "bodyText", "bootstrap3");
|
||||
return GetGridHtml(contentItem, html, "bodyText", "bootstrap3");
|
||||
}
|
||||
|
||||
[Obsolete("This should not be used, GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, string propertyAlias)
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, HtmlHelper html, string propertyAlias)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(propertyAlias, "propertyAlias");
|
||||
|
||||
return GetGridHtml(contentItem, propertyAlias, "bootstrap3");
|
||||
return GetGridHtml(contentItem, html, propertyAlias, "bootstrap3");
|
||||
}
|
||||
|
||||
[Obsolete("This should not be used, GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, string propertyAlias, string framework)
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, HtmlHelper html, string propertyAlias, string framework)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(propertyAlias, "propertyAlias");
|
||||
|
||||
@@ -89,41 +81,68 @@ namespace Umbraco.Web
|
||||
var model = prop.Value;
|
||||
|
||||
var asString = model as string;
|
||||
if (asString.IsNullOrWhiteSpace()) return new MvcHtmlString(string.Empty);
|
||||
if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty);
|
||||
|
||||
return new MvcHtmlString(RenderPartialViewToString(view, model));
|
||||
return html.Partial(view, model);
|
||||
}
|
||||
|
||||
[Obsolete("This should not be used, GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
private static string RenderPartialViewToString(string viewName, object model)
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedProperty property, string framework = "bootstrap3")
|
||||
{
|
||||
var asString = property.Value as string;
|
||||
if (asString.IsNullOrWhiteSpace()) return new MvcHtmlString(string.Empty);
|
||||
|
||||
using (var sw = new StringWriter())
|
||||
var htmlHelper = CreateHtmlHelper(property.Value);
|
||||
return htmlHelper.GetGridHtml(property, framework);
|
||||
}
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem)
|
||||
{
|
||||
return GetGridHtml(contentItem, "bodyText", "bootstrap3");
|
||||
}
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, string propertyAlias)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(propertyAlias, "propertyAlias");
|
||||
|
||||
return GetGridHtml(contentItem, propertyAlias, "bootstrap3");
|
||||
}
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, string propertyAlias, string framework)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(propertyAlias, "propertyAlias");
|
||||
|
||||
var prop = contentItem.GetProperty(propertyAlias);
|
||||
if (prop == null) throw new NullReferenceException("No property type found with alias " + propertyAlias);
|
||||
var model = prop.Value;
|
||||
|
||||
var asString = model as string;
|
||||
if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty);
|
||||
|
||||
var htmlHelper = CreateHtmlHelper(model);
|
||||
return htmlHelper.GetGridHtml(contentItem, propertyAlias, framework);
|
||||
}
|
||||
|
||||
//[Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")]
|
||||
private static HtmlHelper CreateHtmlHelper(object model)
|
||||
{
|
||||
var cc = new ControllerContext
|
||||
{
|
||||
var cc = new ControllerContext
|
||||
{
|
||||
RequestContext =
|
||||
new RequestContext(
|
||||
UmbracoContext.Current.HttpContext,
|
||||
new RouteData() { Route = RouteTable.Routes["Umbraco_default"] })
|
||||
};
|
||||
RequestContext = UmbracoContext.Current.HttpContext.Request.RequestContext
|
||||
};
|
||||
var viewContext = new ViewContext(cc, new FakeView(), new ViewDataDictionary(model), new TempDataDictionary(), new StringWriter());
|
||||
var htmlHelper = new HtmlHelper(viewContext, new ViewPage());
|
||||
return htmlHelper;
|
||||
}
|
||||
|
||||
var routeHandler = new RenderRouteHandler(ControllerBuilder.Current.GetControllerFactory(), UmbracoContext.Current);
|
||||
var routeDef = routeHandler.GetUmbracoRouteDefinition(cc.RequestContext, UmbracoContext.Current.PublishedContentRequest);
|
||||
cc.RequestContext.RouteData.Values.Add("action", routeDef.ActionName);
|
||||
cc.RequestContext.RouteData.Values.Add("controller", routeDef.ControllerName);
|
||||
|
||||
var partialView = ViewEngines.Engines.FindPartialView(cc, viewName);
|
||||
var viewData = new ViewDataDictionary();
|
||||
var tempData = new TempDataDictionary();
|
||||
|
||||
viewData.Model = model;
|
||||
|
||||
var viewContext = new ViewContext(cc, partialView.View, viewData, tempData, sw);
|
||||
partialView.View.Render(viewContext, sw);
|
||||
partialView.ViewEngine.ReleaseView(cc, partialView.View);
|
||||
|
||||
return sw.GetStringBuilder().ToString();
|
||||
private class FakeView : IView
|
||||
{
|
||||
public void Render(ViewContext viewContext, TextWriter writer)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core;
|
||||
@@ -57,7 +58,11 @@ namespace Umbraco.Web.Models
|
||||
|
||||
// these two here have leaked in v6 and so we cannot remove them anymore
|
||||
// without breaking compatibility but... TODO: remove them in v7
|
||||
|
||||
[Obsolete("Will be removing in future versions")]
|
||||
public DynamicPublishedContentList ChildrenAsList { get { return Children; } }
|
||||
|
||||
[Obsolete("Will be removing in future versions")]
|
||||
public int parentId { get { return PublishedContent.Parent.Id; } }
|
||||
|
||||
#region DynamicObject
|
||||
@@ -73,7 +78,9 @@ namespace Umbraco.Web.Models
|
||||
/// <returns></returns>
|
||||
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
|
||||
{
|
||||
var attempt = DynamicInstanceHelper.TryInvokeMember(this, binder, args, new[]
|
||||
var runtimeCache = ApplicationContext.Current != null ? ApplicationContext.Current.ApplicationCache.RuntimeCache : new NullCacheProvider();
|
||||
|
||||
var attempt = DynamicInstanceHelper.TryInvokeMember(runtimeCache, this, binder, args, new[]
|
||||
{
|
||||
typeof(DynamicPublishedContent)
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Dynamic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
@@ -284,8 +285,10 @@ namespace Umbraco.Web.Models
|
||||
return true;
|
||||
}
|
||||
|
||||
var runtimeCache = ApplicationContext.Current != null ? ApplicationContext.Current.ApplicationCache.RuntimeCache : new NullCacheProvider();
|
||||
|
||||
//ok, now lets try to match by member, property, extensino method
|
||||
var attempt = DynamicInstanceHelper.TryInvokeMember(this, binder, args, new[]
|
||||
var attempt = DynamicInstanceHelper.TryInvokeMember(runtimeCache, this, binder, args, new[]
|
||||
{
|
||||
typeof (IEnumerable<DynamicPublishedContent>),
|
||||
typeof (DynamicPublishedContentList)
|
||||
|
||||
Reference in New Issue
Block a user