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!