screen with computer code on it

Surface Controller

Surface Controller

What are Surface Controllers?

Surface controllers are a type of controller in Umbraco, used to manage and handle form submissions, API calls, and any other server-side logic within the Umbraco CMS.

They inherit from the Umbraco.Web.Mvc.SurfaceController class, giving you the ability work well with Umbraco’s content management system, access and modify content easily while using familiar .NET MVC patterns.

Create a form 

create a form within your Umbraco template, set its action route to a method inside a SurfaceController. In this example, our form is pointing to an action called HandleSubmit in a controller named FormController.

Form Example:


<form asp-controller="Form" asp-action="HandleSubmit" method="post">
    <div class="form-group">
        <label for="name">Your Name</label>
        <input type="text" id="name" name="name" class="form-control" required />
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

 

Creating Our Controller 

Next, we need to create a SurfaceController to handle the form submission. This controller will inherit from SurfaceController and include an action method that matches the one specified in the form. In this case, we will create a controller named FormController with an action method called HandleSubmit.

Controller Example:


using Umbraco.Cms.Web.Website.Controllers;
using Microsoft.AspNetCore.Mvc;

public class FormController : SurfaceController
{
    [HttpPost]
    public IActionResult HandleSubmit(string name)
    {
        // Handle form submission logic here
        // For example, save the name to the database or send an email

        TempData["SuccessMessage"] = "Thank you for your submission, " + name + "!";
        
        // Optionally, redirect back to the current page or another page
        return RedirectToCurrentUmbracoPage();
    }
}

Creating Content Programmatically

To create content programmatically in Umbraco using the data gathered from the form, we use the ContentService.

Reference the Content Service: First, get access to the ContentService.


var contentService = Services.ContentService;

Get the Parent Node: Retrieve the parent node (e.g., Home node) under which you want to create the new content.


var homeNode = contentService.GetRootContent().First();

Create the Content: Use the CreateContent method to create the content. This takes three arguments:

  • The name of the content
  • The parent node's ID
  • The model type alias for the content

In this example, we are using the model type alias because we're leveraging Models Builder, which provides strong typing for your content types.


var newCategory = contentService.CreateContent(categoryName, homeNode.Id, "MenuCategory");

For more on Models Builder and why it's beneficial, check out my Models Builder Tutorial 


Save and Publish the Content:
After creating the content, save and publish it just like you would in the Umbraco back office.


contentService.Save(newCategory);
contentService.Publish(newCategory, new string[] { }, -1);

Redirect Back to the Page: Finally, redirect the user back to the home page or another page.


return RedirectToUmbracoPage(homeNode.Key);

Here’s the final controller


using Umbraco.Cms.Web.Website.Controllers;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Services;

public class FormController : SurfaceController
{
    

    [HttpPost]
    public IActionResult HandleSubmit(string categoryName)
    {
        // Step 1: Reference the ContentService 
        var contentService = Services.ContentService;

        // Step 2: Get the Parent Node (Home node in this case)
        var homeNode = contentService.GetRootContent().First();

        // Step 3: Create the Content - Using the model type alias because we are using Models Builder
        var newCategory = contentService.CreateContent(categoryName, homeNode.Id, "MenuCategory");

        // Step 4: Save and Publish the Content
        contentService.Save(newCategory);
        contentService.Publish(newCategory, new string[] { }, -1);

        // Step 5: Redirect to the Home Page
        return RedirectToUmbracoPage(homeNode.Key);
    }
}

Wrap Up:

Surface controllers in Umbraco provide a powerful way to extend the CMS, enabling you to handle form submissions, implement custom logic, and interact with Umbraco content. By inheriting from SurfaceController, you can easily access Umbraco’s content and perform actions like saving, publishing, or redirecting, all while using familiar MVC patterns.

For more detailed information, check out the official Umbraco documentation on Surface Controllers.