If you want to create a custom form within your Umbraco V8 website then you are in the right place. In this tutorial, you will learn how to make use of the surface controller. The surface controller comes with the core framework and it will allow you to create forms that post back to a controller without the need of having to mess around with the routing table. When creating a class that is inheriting from a surface controller, it is best to use it as a component that is contained within a page, rather than trying to apply the surface controller as the page controller. The reason for this is that it will make the process of posting data from the form back to the controller easier later on. In this example, I will assume you have created a standard page that inherits from RenderMvcController and we will build and display this form from within that page

Today we will create a simple contact us form. To create a contact us form we will start off by creating a controller. The code to do this can be seen below:

This controller is split into two actions. The first action will be used to render the custom form. The second action will be used by our form to post data back to the server. Another thing to note in SubmitForm is the ValidateAntiForgeryToken and HttpPost attributes decorated on the action, as well as the use of the IsValid property within the action. When you define the form it is important that you use the correct request type. Failing to specify the correct type may result in a 404 when someone tries to submit a form. ValidateAntiForgeryToken should be used with any .NET form for security.

I have omitted the code that processes the submitted form from the snippet above. In real life, you may want to send an email, store the data to Umbraco, or even forward it to something like salesforce.

After the form has been processed, we can use the TEMPDATA feature to pass information back to the submitted page. TEMPDATA is useful when we work with components on a page to pass data around. When posting back from a component on a page, you will not want to refresh the whole page and potentially lose any submitted data. Using TEMPDATA will allow you to pass data on a component level without a full page refresh!

The View Model

When we want to pass data between the business layer (controller) and the presentation layer (view), you should use a view model. More information on why this is a good practice can be found here. The view model will be used to define the fields that get rendered within the form. The model will also be used to post data back to the server. When building a custom form it is a good idea to also use the ASP.NET annotation attributes to define any validation we want to apply within the form:

You can see that this view model makes use of the Required and MaxLength annotations. There are several more attributes you can use. If you want to learn more you can check out the MSDN page here

The View

Finally, the corresponding form HTML is shown below:

The code above is using BeginUmbracoForm with a POST request to send the data back to the controller. It is using TEMPDATA to render data from the controller after a form has been submitted. Usually, I would always recommend using a view model when working with data being passed down from a controller. As we are working with Umbraco routing and we are building a component that sits on a page then I think this approach is OK as it makes life a lot easier.

Finally, from the containing page, the form component will need to be rendered. This is done using RenderAction, like this:

With this action method, the form should now render from that page and the form should happily post data back to the controller. Happy coding!