---
title: Load resources
slug: cms-12/docs/loading-additional-resources
docTags: 
createdAt: 2026-08-10T15:55:55.000Z
---

:::hint{type="info"}
**Note**
[Optimizely Forms](docId:3SbSlJZIS_3iFmghfQA3J) is only supported by MVC-based websites and HTML5-compliant browsers.
:::

You can load additional resources after form rendering with `IViewModeExternalResources`. Implement the `IViewModeExternalResources` interface to return a list of resources (JavaScript or CSS files) that are loaded into `ViewMode` along with `EPiServerForms.js`.

The interface is used mostly for the following:

- Third-party validators.
- Rich element types (with rich, complex user interface that needs JavaScript to render UI and handle interaction), such as `DateTimeElement` in the `Forms.Samples` project.

```csharp
using EPiServer.Forms.Core;
using EPiServer.ServiceLocation;
using System;
using System.Collections.Generic;

namespace EPiServer.Templates.Alloy.FormsExtended {
  /// <summary>
  /// This example will force Forms.Core to load a JS and a CSS file 
  /// (at http://example.com/Customized/ViewMode/Alloy.css) along with Form rendering
  /// </summary>
  [ServiceConfiguration(ServiceType = typeof (IViewModeExternalResources))]
  public class ExampleViewModeExternalResources: IViewModeExternalResources {
    public IEnumerable<Tuple<string, string>> Resources {
      get {
        var arrRes = new List<Tuple<string, string>>();
        arrRes.Add(new Tuple<string, string>("script", "/Customized/ViewMode/Example.js"));
        arrRes.Add(new Tuple<string, string>("css", "/Customized/ViewMode/Example.css")); 
        // The above line will not work in nonJS mode
        return arrRes;
      }
    }
  }
}
```

## Load embedded resources from separate projects

When developing element blocks in separate projects (for instance, a class library) within your Optimizely solution, you might embed JavaScript or CSS files directly into those projects. Unlike external files accessible through standard web paths, these embedded resources are compiled into your assembly and are not directly addressable by a URL. To load them using the `IViewModeExternalResources` interface, you must first expose them through your main web application.

This typically involves one of two common ASP.NET patterns:

- **Use a custom** `VirtualPathProvider`.
  A `VirtualPathProvider` allows you to map virtual paths (URLs) within your web application to resources that are not physically present in the web project's file system, such as embedded resources in a separate assembly.
  1. **Create a custom** `VirtualPathProvider` – Implement a class that inherits from `VirtualPathProvider` (for ASP.NET) or `IFileProvider` (for ASP.NET Core) to locate and serve your embedded resources. This implementation will typically use `Assembly.GetManifestResourceStream()` to read the embedded file.
  2. **Register the provider** – Register your custom `VirtualPathProvider` with your application at startup.
  3. **Define the virtual paths** – Establish a convention for virtual paths that correspond to your embedded resources (for instance, `~/EmbeddedResources/MyProject/Scripts/my-script.js`).
- **Implement a dedicated controller or handler**.
  Alternatively, you can create a specific controller action or an HTTP handler in your main web project whose sole purpose is to retrieve and serve embedded resources.
  1. **Create a controller action** – Develop a controller action that takes a resource identifier (for instance, assembly name, resource path) as a parameter.
  2. **Retrieve and serve** – Inside the action, use `Assembly.GetManifestResourceStream()` to read the embedded resource and return it as a `FileResult` with the appropriate MIME type.
  3. **Define the route** – Configure a route that maps a URL pattern (for instance, `/embedded-content/{assemblyName}/{resourcePath}`) to this controller action.

### Reference exposed embedded resources

When your embedded resources are exposed and accessible through a URL (whether through a `VirtualPathProvider` or a dedicated controller/handler), you can then reference them in your `IViewModeExternalResources` implementation just like any other external resource:

```csharp
namespace EPiServer.Templates.Alloy.FormsExtended
{
    [ServiceConfiguration(ServiceType = typeof(IViewModeExternalResources))]
    public class ExampleViewModeExternalResources : IViewModeExternalResources
    {
        public IEnumerable<Tuple<string, string>> Resources
        {
            get
            {
                var arrRes = new List<Tuple<string, string>>();
                // Reference an embedded script exposed via a custom mechanism
                arrRes.Add(new Tuple<string, string>("script", "/EmbeddedResources/MyElementBlockProject/Scripts/my-block-script.js"));
                // Reference an embedded stylesheet exposed via a custom mechanism
                arrRes.Add(new Tuple<string, string>("css", "/EmbeddedResources/MyElementBlockProject/Styles/my-block-style.css"));
                return arrRes;
            }
        }
    }
}
```

### Important considerations

- **MIME Types** – Ensure your `VirtualPathProvider` or controller correctly sets the Content-Type header (for instance, application/javascript for .js files, text/css for .css files) to ensure browsers interpret the resources correctly.
- **Caching** – Implement appropriate caching headers to optimize performance for these served resources.
- **Security** – Be mindful of security implications when exposing embedded resources. Ensure that only intended files are served and that no sensitive information is inadvertently exposed.

This approach lets you maintain your element block's resources within its own project while still integrating seamlessly with Optimizely Forms' resource loading mechanism.
