Welcome to the navigation

Amet, est sunt laborum, ipsum in in cupidatat sint dolore exercitation ut qui quis voluptate non in sit consequat, dolore eiusmod enim dolor elit, tempor. Anim enim tempor culpa excepteur lorem dolore labore dolore ex duis ad ea velit non nisi adipisicing magna dolor quis est veniam, elit, nulla sunt

Yeah, this will be replaced... But please enjoy the search!

epi is not defined, $$epiforms is not defined

I got this kind of errors in an Episerver project when implementing Episerver Forms having multiple Layout files with sections.

caught ReferenceError: epi is not defined
    at initializeOnRenderingFormDescriptor (GetFormInitScript?formGuid=8496cfdf-6972-4bec-b4b9-37b4fab4a849&formLanguage=sv:7)
    at GetFormInitScript?formGuid=8496cfdf-6972-4bec-b4b9-37b4fab4a849&formLanguage=sv:31

Uncaught ReferenceError: $$epiforms is not defined
    at WebResource.axd?d=TzRGlCddaaqtz0Im2nSJhMjMKdDD60rloD6JVCAoNhY3gGmphQH9bj5U_X5_FwaUDXIPHIz0lTguiWJkW…:1

The error commonly occurs when you either forgot to include the RequiredClientResources rendering tags or when you are using RenderSections in your layout files. This is by design from Epi but it can be solved pretty easily.

Begin by checking the RequiredClientResources

Did you include the client resource calls in your layout file?

<!-- page head -->
@Html.RequiredClientResources(RenderingTags.Header)

<!-- page bottom -->
@Html.RequiredClientResources(RenderingTags.Footer)

If you did, proceed

The problems with Episerver Forms and @RenderSection

Layout file

Chances are that your _Layout.cshtml (or whatever masterfile you have) containing the basic html looks something like this

<!DOCTYPE html>
<html lang="sv" data-ng-app="app">
<head>
    @Html.RequiredClientResources(RenderingTags.Header)
</head>
<body>
    @Html.Partial("Header")

    <div class="container content">
        @RenderSection("Content", false)
    </div>

    @RenderSection("Scripts", false)

    @Html.RenderEPiServerQuickNavigator()
    @Html.RequiredClientResources(RenderingTags.Footer)
</body>
</html>

Page layout-.cshtml files inheriting the layout

And your other razor files uses the @section pattern

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@section Content{
    <h1>Hello world</h1>
    // ...
}

@section Scripts{
    // ...
}

The issue with this pattern is that RequiredClientResources runs before anything else have been added to the page

Answer from the support from a similar case

When FORM is placed inside @RenderSection, the @Html.RequiredClientResources(RenderingTags.Header) happens before the FormContainerBlockController and it's by designed.

When the FormContainerBlockController is executed, the page already render the header, so FORM cannot add required resources to the header. In order to solve this problem, please move FORM outside @RenderSection.

 

Solving it

There are two ways to solve this issue, both includes using the @RenderBody() method

Simple solution

Skip the Sections and implement a @RenderBody() in the layout file. This will probably result in you segmenting everything into partials including them in your page layout-cshtml files instead. Horrible.

Good solution

This solution require you to add a sort of proxy layout file that will descide which sections that will be rendered in their respective RenderSection of the layout file and which will be rendered by the RenderBody method.

Layout file

Replace the @RenderSection("Content", false) with the @RenderBody() method

<!DOCTYPE html>
<html lang="sv" data-ng-app="app">
<head>
    @Html.RequiredClientResources(RenderingTags.Header)
</head>
<body>
    @Html.Partial("Header")

    <div class="container content">
        @RenderBody()
    </div>

    @RenderSection("Scripts", false)

    @Html.RenderEPiServerQuickNavigator()
    @Html.RequiredClientResources(RenderingTags.Footer)
</body>
</html>

The proxy layout file (new)

Create a new layout file and implement your sections in a similar pattern

@{
    // Select the _Layout file
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@{/*this will forward the scripts section to the Layout file*/}
@if (IsSectionDefined("Scripts"))
{
@section Scripts { @RenderSection("Scripts", false)
} } @******* This will render in RenderBody() *******@ @RenderSection("Content", false) @************************************************@

Page layout-.cshtml files inheriting the layout

Update your references in the cshtml-files, there is no other difference than the Layout reference

@{
    Layout = "~/Views/Shared/_LayoutProxy.cshtml";
}

@section Content{
    <h1>Hello world</h1>
    // ...
}

@section Scripts{
    // ...
}

 

Happy forming!