Web Form

You can create a custom function call editor as a Web Form.

In the following example, the handler is implemented as a Web Form. It shows a simple C1 CMS dialog window where the user is supposed to browse to, and select, an .ascx file.

The custom editor is hooked up to the existing Composite.AspNet.LoadUserControl function, and the path to the file is assigned to its Path parameter.

(You can follow the steps below to create and use this custom editor on the function or install the Composite.Examples.LoadUserControlCallEdit package and study the implementation.)

First, create the handler:

  1. On your website, create a new Web Form named "CallEditor" in, for example, ~/Composite/MyWebForms/Composite.AspNet.LoadUserControl/.
  2. Add the following code to the corresponding Web Form's files:

~/Composite/MyWebForms/Composite.AspNet.LoadUserControl/CallEditor.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="CallEditor.aspx.cs" Inherits="Composite_MyWebForms_Composite_AspNet_LoadUserControl_CallEditor"
	EnableEventValidation="false" ValidateRequest="false" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
	<control:styleloader runat="server" />
	<control:scriptloader type="sub" runat="server" />
	<control:httpheaders runat="server" />
	<title>Composite.AspNet.LoadUserControl</title>
	<script type="text/javascript">
	    ViewDefinitions["Composite.AspNet.LoadUserControl.FileSelector"] = new DialogViewDefinition({
	        isMutable: true,
	        handle: "Composite.AspNet.LoadUserControl.FileSelector",
	        position: Dialog.MODAL,
	        url: Dialog.URL_TREEACTIONSELECTOR,
	        argument: {
	            label: "${string:Composite.Management:Website.FrontendFile.SelectDialog.Title}",
	            image: "${icon:media}",
	            selectionProperty: "ElementType",
	            selectionValue: null,
	            selectionResult: "Uri",
	            nodes: [{
	                key: "WebsiteFileElementProvider"
	            }],
	            width: 480
	        }
	    });
	</script>
</head>
<body>
	<form id="Form1" runat="server" class="updateform updatezone">
	<ui:dialogpage height="990" binding="ResponsePageBinding" responseid="__FunctionMarkup"
		label="Composite.AspNet.LoadUserControl">
		<ui:pagebody>
			<div style="display: none;">
				<textarea runat="server" id="__FunctionMarkup"></textarea>
			</div>
			<aspui:feedback runat="server" id="ctlFeedback" />
			<ui:fields>
				<ui:fieldgroup label="Path">
					<ui:field>
						<ui:fielddesc>
									Select User Control (.ascx)
								</ui:fielddesc>
						<ui:fieldhelp>
									The path to the User Control (.ascx file), like "~/Controls/MyControl.ascx"
								</ui:fieldhelp>
						<ui:fielddata>
							<ui:datainputdialog handle="Composite.AspNet.LoadUserControl.FileSelector" name="txtPath"
								value="<%=ControlPath %>" required="true" binding="" />
						</ui:fielddata>
					</ui:field>
				</ui:fieldgroup>
			</ui:fields>
			<div id="errors" style="display: none">
				<asp:PlaceHolder runat="server" ID="plhErrors"></asp:PlaceHolder>
			</div>
			<ui:dialogtoolbar>
				<ui:toolbarbody align="right" equalsize="true">
					<ui:toolbargroup>
						<aspui:clickbutton id="ClickButton1" customclientid="buttonAccept" client_focusable="true"
							onclick="OnClick" runat="server" text="${string:Website.Dialogs.LabelAccept}" />
						<ui:clickbutton label="${string:Website.Dialogs.LabelCancel}" response="cancel" focusable="true" />
					</ui:toolbargroup>
				</ui:toolbarbody>
			</ui:dialogtoolbar>
		</ui:pagebody>
	</ui:dialogpage>
	</form>
</body>
</html>

~/Composite/MyWebForms/Composite.AspNet.LoadUserControl/CallEditor.aspx.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using Composite.Core.Xml;
using Composite.Functions.Foundation;
using Composite.Core.WebClient.UiControlLib;

public partial class Composite_MyWebForms_Composite_AspNet_LoadUserControl_CallEditor : System.Web.UI.Page
{
    protected string ControlPath;

    private readonly Func<XElement, string, XElement> _getParamElement =
        (functionElement, parameterName) =>
            functionElement.Elements(Namespaces.Function10 + "param").SingleOrDefault(d => d.Attribute("name").Value == parameterName);

    private readonly Func<XElement, string> _getParamValue =
        (parameter) => parameter != null ? (string)parameter.Attribute("value") : "";

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.Form["functionMarkup"] == null)
        {
            ControlPath = Request["txtPath"] ?? string.Empty;
        }
        else
        {
            var functionMarkup = Request.Form["functionMarkup"];
            var functionElement = XElement.Parse(functionMarkup);

            var pathParameter = _getParamElement(functionElement, "Path");
            ControlPath = _getParamValue(pathParameter);
        }
    }

    protected void OnClick(object sender, EventArgs e)
    {
        var path = Request["txtPath"] ?? string.Empty;

        if (path.ToLower().EndsWith(".ascx"))
        {
            var functionElement =
                XElement.Parse(string.Format(@"<f:{0} xmlns:f=""{1}"" />", FunctionTreeConfigurationNames.FunctionTagName,
                                             FunctionTreeConfigurationNames.NamespaceName));

            functionElement.Add(new XAttribute("name", "Composite.AspNet.LoadUserControl"));

            functionElement.Add(new XElement(Namespaces.Function10 + "param",
                                             new XAttribute("name", "Path"),
                                             new XAttribute("value", path)));

            __FunctionMarkup.InnerText = functionElement.ToString();

            ctlFeedback.SetStatus(true);
        }
        else
        {
            plhErrors.Controls.Add(new FieldMessage("txtPath", "Select .ascx control"));
            ctlFeedback.SetStatus(false);
        }
    }
}

Then, register the "CallEditor" Web Form as a function call editor for the Composite.AspNet.LoadUserControl function:

  1. On your website, in ~/App_Code/, create a new class, for example, "LoadUserControlStartupHandler".
  2. Add the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Composite.Core.Application;
using Composite.Functions;

namespace Composite.AspNet
{
	[ApplicationStartup]
	public class LoadUserControlStartupHandler
	{
		public static void OnBeforeInitialize()
		{

		}

		public static void OnInitialized()
		{
			FunctionCallEditorManager.RegisterCustomCallEditor("Composite.AspNet.LoadUserControl",
"~/Composite/MyWebForms/Composite.AspNet.LoadUserControl/CallEditor.aspx",
null, 200);
		}
	}

}

Finally, try and insert the Composite.AspNet.LoadUserControl function on a page and see how the custom editor works.