I have spent many an hour of my life messing around with trying to get information to be passed between different controllers in different states.  A fairly common requirement is having a page that is made up of a form built up via several blocks, for example, a three step checkout process, entering in your information, billing and payment details.

Routing

First off, we need to configure our solution to work with Episerver routing, without this we won't be able to reach our Save action.  The Save action will act as a separate endpoint from the page default index method.

To allow the save action to be accessed from the page a custom route will need to be registered within the route table. The route table is the way you configure your application so it knows when a particular route/URL is made, which controller it should use.  Episerver routing works slightly differently than normal MVC routing, although the underline framework is exactly the same.  To configure your application simply register a generic route as seen below.

Writing Our Form Code

Create a Form page in order for a content editor to add the functionality to the site, this will be a simple page with one Content Area.

In order to display this page, we will need a controller.  In the controller, we will need to add a Save action method.  This method 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 might imagine.  If you have a page type with a custom object of address with an Ignore attribute, that gets bound to the form.  

When you submit the form and get the current page or block back, the Episerver current page object will not be updated.  Instead, you have to use normal vanilla MVC model binding ad pass in the extra object as a parameter of your action method. We will also need a view for our page, with the HTML form.

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.

Next, a new block will be required to display the form. Its job will be to set-up the default properties on the form, like label and place holder text. In this scenario, this block will be called 'ShippingAddressBlock '.

Before we create our shipping block, we need to create a POCO to store our form data in.  This will be done using custom entity called Address, built up like the following:

Create a block with the forms labels and other properties we are interested in

Create the views

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 :)