---
title: XForms
slug: cms-11/dev-docs/xforms-legacy-functionality
docTags: 
createdAt: 2026-07-22T19:45:16.749Z
---

:::hint{type="info"}
**Note**
This content applies to Optimizely Content Management System (CMS) versions 10 and 11.

XForms are deprecated in CMS 12. Use [Optimizely Forms](docId:3SbSlJZIS_3iFmghfQA3J) instead. While existing solutions will continue to work, you should not build new solutions on this API. It will be phased out in the future.
:::

XForms contains logic to store and present forms and data posted from forms. Together with the forms editor in the CMS edit view, it lets editors create and modify forms and view form data. The XForms architecture enables customization, letting developers adapt the XForms functionality.

- Basic concept
- XForms forms management structure
- `EPiServer.XForms` namespace
- `EPiServer.XForms.WebControls` namespace
- Sending form data
- Modifying forms and data
- Working with XForms in MVC

## Basic concept

Editors use the Forms Editor to create forms in edit view. When saved, the form's content is saved as XHTML and XForms markup.

When you present the form, it loads as web controls and renders it as HTML for the client, so there is no need to install additional software to support XForms for the client. When you take this approach, Optimizely CMS does not support the client-side functionality that may be available when you use an XForms browser plug-in.

### Folders for forms

Form folders let you organize a group of forms in a folder structure, which can be useful if the site contains many forms. You also can set a default folder for forms for the entire website or parts of the website, making it easier for editors to manage forms by adding a `DefaultFormFolder` dynamic property and then setting the property value to the folder of your choice for the part(s) of the website you want to affect.

When you create a form page and select a form, the default folder is the starting point for the selection. When you create forms, you should use the default folder. The sample site and language files support this property but do not include it.

## XForms forms management structure

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/iVo5T78UIvWhqijgOMN8u-20260722-194633.png "xforms.png")

1. You create a form in the Form Editor in CMS.
2. [EPiServer.XForms](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/F4EB3A06) converts the form to XHTML and XForms.
   Repeat Steps 1 and 2 until the form is how you want it.
3. The form is sent to the client as HTML through [EPiServer.XForms](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/F4EB3A06). You can alter the form before presenting it to the client by attaching it to events.
4. Data is posted and validated. If the input is not validated, it sends error messages to the client. (You also can have additional validation on the client before sending the form to the server by setting the `EnableClientScript` property to **true** on the XFormControl web control.)
5. Form data is passed into the Optimizely CMS data warehouse through \[EPiServer. XForms] (). You can send the posted data by email or to a custom URL.
6. If you save the data to the database, you can load and show the posted data on the website.

## EPiServer.XForms namespace

### XForm class

The [XForm](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/5F33C154) class represents the content and the structure of the form. It saves the content of the form as XML. The XML contains the **instance** node, which contains the data for the form, such as field validation and default values for fields. It also stores information about the structure of the form; this is stored as XHTML with controls from the XForms namespace. This class creates a default [XFormData](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/CF2C1244) object from its instance node.

The following code shows an example of an XForm's content. When you export a form with the CMS forms editor, the form content is represented in this format.

```xml
<root xmlns:xforms=a href="http://www.w3.org/2002/xforms">http://www.w3.org/2002/xforms</a>
          xmlns:xsi=<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>>
      <model>
        <instance>
          </Author />
        </instance>
      </model>
      <table id="id_matrix" border="0">
        <tr>
          <td valign="top" width="100" height="10">
            <span id="id_fields1">Author</span></td>
          <td valign="top" width="200" height="10">
            <xforms:input ref="Author" value="" id="id_fields2" size="40" /></td>
        </tr>
      </table>
    </root>
```

:::hint{type="info"}
**Note**
Even though this example shows a form that is structured using HTML tables, there are no limitations for the structure of the form to use other elements, such as the `<div>` element. In CMS, the built-in form editor creates a form using HTML tables.
:::

### XFormData class

The [XFormData](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/CF2C1244) class contains information on the content of a posted form. Normally, when you post a form, you create an `XFormData` class instance, but you can also define an old post when loading a form to re-edit data. The `XFormData` class represents existing data when loading form data for a form.

### DataTypes class

The [DataTypes](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/11DAF82D) class contains information about the data types for form fields in a public `Types` property is a hash table containing keys and values, where keys are the unique keys for the data type, and the value is a regular expression.

When you post form data, it validates the input against the regular expression for the data type of the input control. If you do not specify a data type for the control, it validates the data against the public `InvalidDefaultInputRegex` string property. A default validation prevents malicious data from being posted from a form.

## EPiServer.XForms.WebControls namespace

### XFormControl class

[XFormControl](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/91E2438D) is a web control that displays an XForms form and verifies the input. The class exposes a public method, [SubmitForm](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/FB7AA338), to be able to submit form data. The form itself does not trigger the actual posting; it is handled by any existing submit web controls in the form, which is also why you can have several buttons on the same form that may trigger different actions. Of course, you can also call this method from the code.

What happens when the form is loaded?

1. The `BeforeLoadingForm` event is triggered. You can alter the XForm definition here by changing the `FormDefinition` property of the `LoadFormEventArgs` that is sent to the event handler. (For instance, you could replace the **table** structure with a **div** structure by applying regular expressions to the form content).
2. The XML from the `FormDefinition.Document` property is parsed by `Page.ParseControl`, which adds the parsed controls as child controls. These would be Literal controls for the HTML and form web controls derived from `XFormControlBase`.
3. For fields that have validation, validation control(s) are added and connected to the corresponding web control.
4. `ControlsCreated` is a triggered public event. At this time, you can alter the form's appearance and function.
5. The rendering of the form takes place as XHTML.

What happens when data is submitted?

1. A submit control triggers the `SubmitForm` event. If defined on the submit control, the submit sets values for email and custom URL to the `XFormControl` containing the forms data property. The `SubmitForm` method is called with the channel options set on the submit control. See Sending Form Data for information about available channels.

\{ /\*\*/ }

1. Validation ensures you follow the rules about anonymous users and multiple postings from the same user. If there are validation errors against these rules, `StaticValidators` are added to the `Page.Validators` collection to ensure that validation errors occur. A `StaticValidator` is a validator that gives a validation error.
2. `BeforeReadingPostedData` is a triggered public event and `Page.Validate()` is called for the current validation group. If the `CancelSubmit` property is set to **true**, it add a `StaticValidator` for strings in the `ErrorMessages` array. Any validation errors to the XForm controls also result in validation errors and cancel the form posting with a list of validation errors.
3. `BeforeSubmitPostedData` is a triggered public event, and any event handlers that sets `CancelSubmit` to **true** cancel the form posting.
4. Xforms sends the form data to the specified channel. If the user is anonymous, it sets a cookie to indicate that it posted the form.
5. `AfterSubmitPostedData` is a triggered public event.

### XForms web controls

The following table shows the controls and their corresponding HTML tags used while rendering themselves:

| Web Control                      | HTML                        |
| -------------------------------- | --------------------------- |
| Input                            | `<input />`                 |
| Select                           | `<input type=”checkbox” />` |
| Select1, with Rendertype.Full    | `<input type=”radio” />`    |
| Select1, with Rendertype.Minimal | `<select></select>`         |
| Submit                           | `<input type=”submit” />`   |
| TextArea                         | `<textarea></textarea>`     |
| Secret                           | Not implemented             |

## Send form data

You can send an `XFormData` object to different channels. A channel might be storage in the database, an email address or a URL. The `ChannelOptions` property specifies one or several channels where it sends the data.

| Channel Name | Description                                                                                   |
| ------------ | --------------------------------------------------------------------------------------------- |
| Database     | The entire `XFormData` object is serialized and saved to the `tblItem` table in the database. |
| Email        | The content of the form data is transformed using a predefined XSLT.                          |
| CustomUrl    | The values for the form are uploaded to a URL using the `System.Net.WebClient` class.         |

## Modify forms and data

### Work with form postings

In CMS, the XForm class has several methods for accessing form data. [GetPostedData](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/5FE7B5FC) lists form data objects that specify certain criteria, such as posted date, form, and page ID. In CMS, there are overloads of this method that supports paging also. [GetPostedDataCount](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/C122AC63) gets the number of users that have posted data to a form, and [GetPostedDataStatistics](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/6DBF9325) calculates statistics for a form directly in the database.

### Retrieve and modify previously posted data

You can re-edit data that is posted to the database (or another custom location if you can load and save the `XFormData` object). To do this, create an `XFormControl` object and set its `Data` property to the `XFormData` object you want to load. It loads the form with the values from the posted data. If it posts the data to the database, it replaces the old data.

You also could load an `XFormData` object and modify the object programmatically. By using the `Send` method, you can store the modified content again.

### Edit the appearance of a form

There are two main ways to edit the appearance of a form.

1. Edit the content of the form in the `BeforeLoadingFormsEvent`. If you do this, it might affect the behavior of the built-in form editor. The `LoadFormsEventArgs` class has an `EditMode ` property that defines whether the form is loaded in edit view, which lets you only change the form to the end user, thus not affecting the Optimizely CMS edit mode.
2. Attach to the `ControlsCreated` event for the `XFormControl` object. The content of the form is parsed and added to the `Controls` collection. Xforms parses the HTML content as **Literal** controls, and the `XForm` controls as the different controls in the `EPiServer.XForms.WebControls` namespace. There should not be any problems modifying the HTML content.

If you want to change the appearance of the XForm web controls, add or modify the attribute collection for the control. By using CSS and setting the class attribute for the control, you could do a lot for the appearance of the form control. In Optimizely CMS the [ExtractXFormControls](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/8DA4FF61) method gets an `ArrayList` containing the input elements for the form.

### Send customized emails

When you use the **email option** for sending `XFormData`, the content of the form data is transformed using an XSLT schema. Unfortunately, you cannot specify a custom XSLT schema to transform the form data to an email. You can still implement your email handling by adding custom logic to the `BeforeSubmitPostedData` event on the `XFormControl` web control. Before exiting your custom logic, remove the email option from the `e.FormData.ChannelOptions` property to ensure that the regular email channel is not triggered.

If you set `e.FormData.ChannelOptions` to `ChannelOptions.None`, you lose additional channels to which the form data is sent, such as the Database Channel.

## Work with XForms in MVC

When you use XForms with MVC, required functionality is automatically injected into the controller when using the [ActionControllerBase](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/101072C6) base class (which, for example, `PageController<T>` inherits from). Use the normal HTML-helper `Html.PropertyFor` in the view to render the XForm.

Static events on the [XFormActionHelper](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/17DD4284) class exist for [BeforeSubmitPostedData](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/51949181) and [AfterSubmitPostedData](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/86B89A58) to listen and act on posted data through MVC for the whole site.

You can also handle the posting using a method on the controller. To take more control over the posting, add an [XFormParameters](https://world.optimizely.com/documentation/Class-library/?documentId=cms/10/9F8CF33A) instance to the following:

```csharp
PropertyFor: @Html.PropertyFor(x => x.CurrentContent.MyForm, new {
  XFormParameters = new EPiServer.XForms.Util.XFormParameters() {
    PostAction = "Posted", SuccessAction = "Success", FailedAction = "Failed"
  }
})
```

In the `XFormParameters` class, you can specify the methods to use when you post the XForm, the methods to use when the user gets validation errors, and when the XForm gets posted. The controller may look something like the following code when you take care of the post action:

```csharp
public class XFormPageController: PageController < XFormPage > {
  private XFormPageUnknownActionHandler _xformHandler;

  public XFormPageController(XFormPageUnknownActionHandler xformHandler) {
    _xformHandler = xformHandler;
  }

  public ActionResult Index(PageData currentPage) {
    return View(currentPage);
  }

  #region Success and failed actions

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Success(PageData currentPage, XFormPostedData xFormPostedData) {
    return View("Success", currentPage);
  }

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Failed(PageData currentPage, XFormPostedData xFormPostedData) {
    return View("Failed", currentPage);
  }

  #endregion

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult DoSubmit(XFormPostedData xFormpostedData) {
    return _xformHandler.HandleAction(this);
  }
}
```

### Validation

Xforms performs validation when you use the `XFormHandler` on the server side. To enable client validation, add the HTML-helper `EnableClientValidation` in your view.

### Render

To render an XForm property on a page, use the `Property` and `RenderPropertyXForm` HTML helper methods in the view. The Property method uses the default behavior, while the `RenderPropertyXForm` takes the name of the property and an `XFormParameters` class as parameters. Optionally use the `XFormParameters` parameter to override the default settings.

If you do not set the `SuccessAction` and `FailedAction `properties on the `XFormParameters` class, the system uses default views for successful and failed posts. If you set `SuccessAction` to **Success** and `FailedAction` to **Failed**, the system calls the Success or Failed action in the controller, depending on whether a validation error occurred when posting the form. To make it work, you must create the Success and Failed methods in the controller.

```csharp
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <%@ Import Namespace="EPiServer.XForms.Util" %>
    
    <section id="form">
        <%--<% Html.EnableClientValidation(); %>--%>
        <%: Html.ValidationSummary() %>
        <% Html.RenderPropertyXForm("XForm", new XFormParameters() { SuccessAction = "Success", FailedAction = "Failed" }); %>
        <%--<%: Html.Property("XForm") %>  --%>
    </section>
```
