In this tutorial, you will learn how to create a form within an Episerver CMS powered website that can post back to a controller. CMS routing can be a tricky beast. In some situations, Episerver works in a similar way as normal .NET, however, the routing rules work differently. This difference can catch a lot of developers out. I will not lie, have spent many an hour of my life frustrated with routing. Trying to get information to successfully be passed between views and controllers is often a tedious chore. The aim of this post is to save you the same pains!

Routing

To get a form to post back to a controller, you will need to create a rule in the routing table. Without this rule, the request will 404. In this example, I will create an action called Save. The Save action will act as a separate endpoint. The default page action named index will be used to render the form and save will be used to process its results. To allow the view file to post back to the Save action, a custom route will need to be registered within the routeing table. If you have not come across the routing table before then this is not an Episerver specific thing, it is a default Microsoft ASP.NET feature. The routing table allows a developer to configure an application to map a URL to the controller and action that the ASP.NET pipeline should call.

To configure your form to post back, you can define this route. This code should be placed in the global.asax:

For this example, I will create a page type called form and we will create the form within a block called ShippingAddressBlock. ShippingAddressBlock will be added onto the page within a content area called MainContentArea. In the real world, you can add a form to whatever page you wish. The code to create this example page type is shown below:

In order to display this page on the website, you will need to create a corresponding page type controller. In the controller, we will need to add the Index and the Save action. The Save action will be called when a user clicks the form submission button.

The processing of submitting the form back to the controller might not work as you expect. When you submit the form and a postback occurs, the Episerver current page object will not be automatically available within the controller. Instead, you have to use normal vanilla MVC model binding and bind the current page object with the form submissions. You will then need to define an extra parameter on the Save action to access it! We will cover the code to do this in a bit, for now, keep a mental note that the current page object needs to be passed back in the form!

We will also need a view for our page to render the form, with a PropertyFor() helper to render the content area that will contain the form block. The HTML for the page view could look like this::

Notice how the BeginForm code is added to the page view and not the block view! At this point, a view exists that contains a button. When the button is clicked a request is made back to a custom action within the form controller. This process works by creating a custom route within the route table. We now need the block view to render the form elements. The purpose of this block will is to set up the default properties on the form, like labels and placeholder text. In this example, this block will be called 'ShippingAddressBlock '. Before we create our shipping block, we need to create a POCO to store the form data. using a separate object will make life easier. In this example, this entity will be called Address. Below defines the code required to build this object:

next we need to define the block definition:

Note that on Line 12 ShippingAddress is exposed as a public property. This is the model that will be bound to the form. This page type is defining two types of data. Properties for content editors to use in the CMS and an object that is used to bind an object to a form. I use the Ignore attribute so this item does not appear within the editor. We want to use this within the view only. Next, we need to create the view that will contain the form:

The form is then used to render the form elements. Above is an overview of all files in the final solution. Please note that argument and service call validations have been omitted to keep the code as simple as possible.  You can also find all of this code on my GitHub account at the link here, good luck! When trying to get this to work, it is usually the routing that causes the pain. Happy Coding 🤘