When you have a UserControlFunction which has a XhtmlDocument FunctionParameter and you put another UserControlFunction inside that XhtmlDocument property using a VisualXhtmlEditor it will raise an error when trying to render/parse the user control.
Basically what happens is that when parsing the first/top UserControlFunction it also executes and replaces all functions with in its XhtmlDocument parameters. The functions inside that parameter will be converted from its f:function markup to c1:marker with a key to the UserControl, but the context the created control is stored in is not available when rendering the XhtmlDocument parameter ( e.g. through a c1:Render tag or manually parsing the XhtmlDocument using PageRenderer.ExecuteEmbeddedFunctions etc ).
In previous versions of Composite I was able to accomplish nesting of XhtmlDocuments with functions by using a String FunctionParameter with additional WidgetMarkup for the VisualXhtmlEditor.
The issue exists both in Composite 4.1 and the latest development build.
I have tracked down the issue in the latest source and have it working by changing the above described behaviour.
Instead of executing functions in XhtmlDocument parameters it now just passes the source and the UserControl itself can then parse underlaying elements/functions using normal c1:render markup or by manually executing embedded functions and converting them into .net controls.
UserControlBasedFunction.cs
```
public override object Execute(Composite.Functions.ParameterList parameters,
Composite.Functions.FunctionContextContainer context)
{
var httpContext = HttpContext.Current;
Verify.IsNotNull(httpContext, "HttpContext.Current is null");
Page currentPage = httpContext.Handler as Page;
Verify.IsNotNull(currentPage, "The Current HttpContext Handler must be a " + typeof (Page).FullName);
var userControl = currentPage.LoadControl(VirtualPath);
foreach (var param in parameters.AllParameterNames)
{
/*
Changed so that XhtmlDocument parameters are not executed within this context but are directly assigned to the usercontrol
*/
Composite.Functions.ParameterList.StoredParameterReturnValue storedParameterReturnValue;
bool parameterFound = parameters.TryGetValue(param, out storedParameterReturnValue);
if (parameterFound && storedParameterReturnValue.ValueType==typeof(Composite.Core.Xml.XhtmlDocument))
{
Composite.Functions.XElementParameterRuntimeTreeNode element = storedParameterReturnValue.ValueObject as Composite.Functions.XElementParameterRuntimeTreeNode;
Composite.Core.Xml.XhtmlDocument doc = new Core.Xml.XhtmlDocument(element.GetHostedXElement());
Parameters[param].SetValue(userControl, doc);
}
else
{
var value = parameters.GetParameter(param);
Parameters[param].SetValue(userControl, value);
}
}
return userControl;
}
```
Inside ParameterList.cs I had to add a TryGetValue function to only get the parameter value without executing it.
```
public bool TryGetValue(string parameterName, out StoredParameterReturnValue value)
{
StoredParameterReturnValue storedParameterReturnValue;
bool parameterFound = _parameters.TryGetValue(parameterName, out storedParameterReturnValue);
if (!parameterFound)
{
value = null;
return false;
}
else
{
value = storedParameterReturnValue;
return true;
}
}
```
Perhaps none of the parameters inside a UserControlFunction should be executed, but just to be sure I check if it the parameter type is a XhtmlDocument and if so just return the parameter XElement value as a new XhtmlDocument.
Comments: ** Comment from web user: jaouw85 **
Basically what happens is that when parsing the first/top UserControlFunction it also executes and replaces all functions with in its XhtmlDocument parameters. The functions inside that parameter will be converted from its f:function markup to c1:marker with a key to the UserControl, but the context the created control is stored in is not available when rendering the XhtmlDocument parameter ( e.g. through a c1:Render tag or manually parsing the XhtmlDocument using PageRenderer.ExecuteEmbeddedFunctions etc ).
In previous versions of Composite I was able to accomplish nesting of XhtmlDocuments with functions by using a String FunctionParameter with additional WidgetMarkup for the VisualXhtmlEditor.
The issue exists both in Composite 4.1 and the latest development build.
I have tracked down the issue in the latest source and have it working by changing the above described behaviour.
Instead of executing functions in XhtmlDocument parameters it now just passes the source and the UserControl itself can then parse underlaying elements/functions using normal c1:render markup or by manually executing embedded functions and converting them into .net controls.
UserControlBasedFunction.cs
```
public override object Execute(Composite.Functions.ParameterList parameters,
Composite.Functions.FunctionContextContainer context)
{
var httpContext = HttpContext.Current;
Verify.IsNotNull(httpContext, "HttpContext.Current is null");
Page currentPage = httpContext.Handler as Page;
Verify.IsNotNull(currentPage, "The Current HttpContext Handler must be a " + typeof (Page).FullName);
var userControl = currentPage.LoadControl(VirtualPath);
foreach (var param in parameters.AllParameterNames)
{
/*
Changed so that XhtmlDocument parameters are not executed within this context but are directly assigned to the usercontrol
*/
Composite.Functions.ParameterList.StoredParameterReturnValue storedParameterReturnValue;
bool parameterFound = parameters.TryGetValue(param, out storedParameterReturnValue);
if (parameterFound && storedParameterReturnValue.ValueType==typeof(Composite.Core.Xml.XhtmlDocument))
{
Composite.Functions.XElementParameterRuntimeTreeNode element = storedParameterReturnValue.ValueObject as Composite.Functions.XElementParameterRuntimeTreeNode;
Composite.Core.Xml.XhtmlDocument doc = new Core.Xml.XhtmlDocument(element.GetHostedXElement());
Parameters[param].SetValue(userControl, doc);
}
else
{
var value = parameters.GetParameter(param);
Parameters[param].SetValue(userControl, value);
}
}
return userControl;
}
```
Inside ParameterList.cs I had to add a TryGetValue function to only get the parameter value without executing it.
```
public bool TryGetValue(string parameterName, out StoredParameterReturnValue value)
{
StoredParameterReturnValue storedParameterReturnValue;
bool parameterFound = _parameters.TryGetValue(parameterName, out storedParameterReturnValue);
if (!parameterFound)
{
value = null;
return false;
}
else
{
value = storedParameterReturnValue;
return true;
}
}
```
Perhaps none of the parameters inside a UserControlFunction should be executed, but just to be sure I check if it the parameter type is a XhtmlDocument and if so just return the parameter XElement value as a new XhtmlDocument.
Comments: ** Comment from web user: jaouw85 **
I have the same problem with this.
I can add serveral Functions to the XhtmlDocument, however if i include a UserControl based function i get the error.