What Is An Umbraco Surface Controller?

Mastering Surface controllers will make your life easier when working with forms in Umbraco. I've written about route hijacking before within an Umbraco website. Route Hijacking, will tel your website how to route a virtual page request to your MVC controller. In today's guide, we'll take the process one step further and talk about Surface controllers

What is a surface controller?

When we work with plain old MVC, controllers are defined by creating a class and inheriting from 'Controller'. A surface controller is an Umbraco specific controller. If you use Reflector to look at the surface controllers base code you will notice that it inherits from the normal MVC controller. A surface controller can do everything a normal MVC controller can do. The reason why you'd use a surface controller is that it does some extra Umbraco specific features behind the hood when it comes to works. To be really clear, if you have a web page and the only thing you want to do is display some text, then use RenderMvcController, or, a normal MVC controller. If you need a page that has a custom form on it, like a login form, a contact me form, or a search box uses a surface controller. Before we go into some code, it's probably a good idea to talk about what exactly these Umbraco related things are. The two-bit points are, a surface controller has access to the current page Umbraco object.

How To Create A Surface Controller

To create a surface controller, create a new class in your projects 'Controllers' folder. Your controller's name needs to always end in Controller.cs (like MVC). This class will need to inherit from the SurfaceController.
using Umbraco.Web.Mvc.SurfaceController;

public class LoginPageSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
   public ActionResult DisplayForm()
   {
       return PartialView("LoginPage", new LoginPageViewModel());
   }

   [HttpPost]
   [ValidateAntiForgeryToken]
   public ActionResult FormSubmission(LoginPage ViewModelmodel)
   {
        // Do stuff
   }
}

The code above is pretty straightforward. I've defined two actions, one to render the page and one to deal with a form submission. It's the surface controllers job that will allow the form submission action to correctly route with the right parameters when a website visitor submits a form. In the example above, for brevity, I've missed out a lot of code. If you want to create a log-in page, then I suggest you read, How To Create a Login Page With Umbraco 7 which will fill in all the gaps. If you tried to post back to a controller without it inheriting from the Surface Controller, Umbraco wouldn't know which controller to call. Writing Umbraco MVC, as you can see is very similar to normal ASP.NET MVC. Getting the Surface controller to post back and submit can take a while to get right. If you are struggling don't worry as I did as well. Below lists some useful tips:
  • The display action and the post submission action names need to be different. If you don't do this Umbraco can get its knickers in a twist
  • A surface controller isn't used on a page. A surface controller is used in a partial controller
  • The Submit action has to use the [HttpPost]
Your view, would then look something like this:
	@model JonDJones.Core.Entities.ContactEnquiryModel


    using (Html.BeginUmbracoForm<LoginPageSurfaceController >("FormSubmission"))
    {
    	<input type="submit" value="Submit" class=" button_medium" id="submit-contact" />
                        
        @Html.ValidationSummary(true)
         @Html.AntiForgeryToken()

    }
This is a very simple example, you will need to use the 'BeginUmbracoForm' helper to get started. One even stupid thing I did the first time I tried to implement a surface controller, we to accidently leave a HTML
tag in between BeginUmbracoForm. Do NOT do this because it will screw everything up! I got the following error for reference 'Can only use UmbracoPageResult in the context of an Http POST when using a SurfaceController form'
 @Html.Action("DisplayForm", "LoginPageSurface")
To call a view with a surface controller on it, you would use a

Surface Controllers Take Away

If you need to get information back from your users, whether it be a form, a log-in page etc.. you will need to use a surface controller in order for the postback to call the correct controller. As you can see from the code above, except for a few differences like the name you have to call your controller and the type you inherit from, the code looks pretty much the same as a standard MVC controller. This is because Umbraco isn't rewriting the rule book, instead it's working with the framework and adding hooks in at certain points.


Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge


Back to top
var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-35662136-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'stats.g.doubleclick.net/dc.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();