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!