Creating Episerver Forms programmatically

I recently had to automate the process of creating Episerver Forms. In this blog post, I will show you how to create Episerver Forms from the code.

Let's say we have the following page type:

[ContentType(GUID = "...")]
public class MyPage : PageData
{
    public virtual ContentArea FormsContentArea { get; set; }
}

When MyPage is created, we want to create a new form and add it inside MyPage.FormsContentArea.

To do that, we can create an initialization module that listens to content events.

[InitializableModule]
[ModuleDependency(typeof(InitializationModule))]
public class FormsCreationModule : IInitializableModule
{
    private IContentRepository _contentRepository;
    private ContentAssetHelper _contentAssetsHelpers;

    public void Initialize(InitializationEngine context)
    {
        _contentRepository = context.Locate.Advanced.GetInstance<IContentRepository>();
        _contentAssetsHelpers = context.Locate.Advanced.GetInstance<ContentAssetHelper>();

        var contentEvents = context.Locate.Advanced.GetInstance<IContentEvents>();
        contentEvents.CreatedContent += ContentEvents_CreatedContent;
    }

    public void Uninitialize(InitializationEngine context)
    {
        var contentEvents = context.Locate.Advanced.GetInstance<IContentEvents>();
        contentEvents.CreatedContent -= ContentEvents_CreatedContent;
    }

    private void ContentEvents_CreatedContent(object sender, ContentEventArgs e)
    {
        if (e.Content is MyPage myPage)
        {
            AutoGenerateForm(myPage);
        }
    }

    private void AutoGenerateForm(MyPage myPage)
    {
        var pageAssetsFolder = _contentAssetsHelpers.GetOrCreateAssetFolder(myPage.ContentLink);
        var formContainerBlock = _contentRepository.GetDefault<FormContainerBlock>(pageAssetsFolder.ContentLink);

        ((IContent)formContainerBlock).Name = myPage.Name + " - form";
        formContainerBlock.AllowAnonymousSubmission = true;

        // we need to save the form container to get its Assets Folder.
        _contentRepository.Save(
            formContainerBlock as IContent,
            SaveAction.Save,
            AccessLevel.NoAccess);


        var formAssetsFolder = _contentAssetsHelpers.GetOrCreateAssetFolder(
            ((IContent)formContainerBlock).ContentLink);

        if (formContainerBlock.ElementsArea == null)
        {
            formContainerBlock.ElementsArea = new ContentArea();
        }


        var fullNameBlock = CreateFormElement<TextboxElementBlock>(
            name: "Full name",
            label: "Full name",
            parentLink: formAssetsFolder.ContentLink);
        
        formContainerBlock.ElementsArea.Items.Add(new ContentAreaItem
        {
            ContentLink = ((IContent)fullNameBlock).ContentLink
        });

        
        var emailBlock = CreateFormElement<TextboxElementBlock>(
            name: "Email",
            label: "Email",
            validators: typeof(EmailValidator),
            parentLink: formAssetsFolder.ContentLink);

        formContainerBlock.ElementsArea.Items.Add(new ContentAreaItem
        {
            ContentLink = ((IContent)emailBlock).ContentLink
        });


        var submitButtonBlock = CreateFormElement<SubmitButtonElementBlock>(
            name: "Submit button",
            label: "Send",
            parentLink: formAssetsFolder.ContentLink);

        formContainerBlock.ElementsArea.Items.Add(new ContentAreaItem
        {
            ContentLink = ((IContent)submitButtonBlock).ContentLink
        });
       

        _contentRepository.Save(
            formContainerBlock as IContent,
            SaveAction.Publish,
            AccessLevel.NoAccess);

        // myPage.FormsContentArea is read-only.
        // we need to create a writable clone.
        var clone = myPage.CreateWritableClone() as MyPage;

        if (clone.FormsContentArea == null)
        {
            clone.FormsContentArea = new ContentArea();
        }

        clone.FormsContentArea.Items.Add(new ContentAreaItem
        {
            ContentLink = ((IContent)formContainerBlock).ContentLink
        });

        _contentRepository.Save(clone, AccessLevel.NoAccess);
    }

    private T CreateFormElement<T>(
        string name,
        string label,
        ContentReference parentLink,
        params Type[] validators
    )
        where T : ElementBlockBase
    {
        var block = _contentRepository.GetDefault<T>(parentLink);
        ((IContent)block).Name = name;
        block.Label = label;

        // add validators
        if (validators != null && validators.Length > 0)
        {
            var validatableBlock = block as ValidatableElementBlockBase;
            if (validatableBlock != null)
            {
                validatableBlock.Validators = string.Join(
                    Constants.RecordFieldSeparator,
                    validators.Select(x => x.FullName));
            }
        }

        _contentRepository.Save((IContent)block, SaveAction.Publish, AccessLevel.NoAccess);

        return block;
    }
}

Page

Creating Episerver Forms from the code

Form container block

Creating Episerver Forms from the code

 

comments powered by Disqus