Blog about tips & tricks for CMS enhancement

eric.petersson

Create a Custom Episerver Forms Email Template programmatically


Last week, Dejan Caric posted an entry about Creating Episerver Forms Programmatically which in the time given solved some client features that I also had to implement in a similiar way.

One thing though was how to auto generate the form settings for my client whom always would like to have some basic setups for Episerver Forms when creating certain page types. To accomplish this, I added the following snippet of code to Dejan Ceric's code:

            var emailActorModels = formContainerBlock.Content.Property.GetPropertyValue<IEnumerable<EmailTemplateActorModel>>("SendEmailAfterSubmissionActor");
            var customEmailTemplate = new List<EmailTemplateActorModel>();

            if (emailActorModels == null || emailActorModels.Count() == 0)
            {
                customEmailTemplate.AddRange(new List<EmailTemplateActorModel>
                {
                    new EmailTemplateActorModel
                    {
                        Subject = "My programmatically subject here",
                        FromEmail = "noreply@episerver.com",
                        ToEmails ="#E-mail#",
                        Body = new XhtmlString("<p>Hi #fullname#</p>" +
                            "Thank you for submitting the form. We have received the following information from you and will return shortly to address next steps for further proceeding:" +
                            "#summary#")
                    }
                });
            }

            formContainerBlock.Content.SetPropertyValue("SendEmailAfterSubmissionActor", customEmailTemplate);      

By implementing some values for the EmailTemplateActorModel and assigning them with SetPropertyValues("SendEmailAfterSubmissionActor").

The # indicates an identification to the form fields. By implementing #E-mail#, #fullname# and #summary# you may refer to the fields entered by your visitors for the Episerver Forms.

We may after creating our page of special kind receive  not just the form we need, but also some standard values like below.

Implementing some default values programmatically for the Email template in Episerver Forms.

The total InitilizationModule code behind looks like the following for my client:

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class EpiserverFormsCreateInitialization : 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 MyPageType myPageType)
        {
            AutoGenerateForm(myPageType);
        }
    }

    private void AutoGenerateForm(MyPageType myPageType)
    {
        var pageAssetsFolder = _contentAssetsHelpers.GetOrCreateAssetFolder(myPageType.ContentLink);
        var formContainerBlock = _contentRepository.GetDefault<FormContainerBlock>(pageAssetsFolder.ContentLink);
        var parent = _contentRepository.Get<IContent>(myPageType.ParentLink);

        ((IContent)formContainerBlock).Name = $"[Online Form] - {parent.Name} - {myPageType.Name}";

        // 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();
        }

        // setup standard values for the form
        GenerateStandardFormBlocks(formAssetsFolder, formContainerBlock);
        GenerateStandardSettingsForForm(formContainerBlock, parent);

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

        var clone = myPageType.CreateWritableClone() as MyPageType;

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

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

        _contentRepository.Save(clone, AccessLevel.NoAccess);
    }
    
    private void GenerateStandardFormBlocks(ContentAssetFolder formAssetsFolder, FormContainerBlock formContainerBlock)
    { 
        var emailBlock = CreateFormElement<TextboxElementBlock>(
            name: "E-mail",
            label: "E-mail",
            validators: new[] { typeof(RequiredValidator), typeof(EmailValidator) },
            parentLink: formAssetsFolder.ContentLink);

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

        var elements = formContainerBlock.ElementsArea.Items;

        elements.AddRange(new List<ContentAreaItem>
        {
            new ContentAreaItem { ContentLink = ((IContent)emailBlock).ContentLink },
            new ContentAreaItem { ContentLink = ((IContent)submitButtonBlock).ContentLink }
        });           
    }

    private void GenerateStandardSettingsForForm(FormContainerBlock formContainerBlock, IContent parent)
    {
       var emailActorModels = formContainerBlock.Content.Property.GetPropertyValue<IEnumerable<EmailTemplateActorModel>>("SendEmailAfterSubmissionActor");
            var customEmailTemplate = new List<EmailTemplateActorModel>();

            if (emailActorModels == null || emailActorModels.Count() == 0)
            {
                customEmailTemplate.AddRange(new List<EmailTemplateActorModel>
                {
                    new EmailTemplateActorModel
                    {
                        Subject = "My programmatically subject here",
                        FromEmail = "noreply@episerver.com",
                        ToEmails ="#E-mail#",
                        Body = new XhtmlString("<p>Hi #fullname#</p>" +
                            "Thank you for submitting the form. We have received the following information from you and will return shortly to address next steps for further proceeding:" +
                            "#summary#")
                    }
                });
            }

            formContainerBlock.Content.SetPropertyValue("SendEmailAfterSubmissionActor", customEmailTemplate);
    }

    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;

        if (validators != null && validators.Length > 0)
        {
            var validatableBlock = block as ValidatableElementBlockBase;
            if (validatableBlock != null)
            {
                validatableBlock.Validators = string.Join(";", validators.Select(v => v.FullName));
            }
        }

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

        return block;
    }
}