TOP
EL EN
Creating a Registration Page in Umbraco
15 September 2024 Published by Aristotelis Pitaridis
Tools used for this tutorial
Microsoft Visual Studio Community 2022 17.10.5
Umbraco 14.2.0
Bootstrap 5.0.2
SHARE

Introduction

Umbraco is a powerful and flexible content management system (CMS) that allows developers to create custom websites with ease. In this guide, we will walk you through the process of creating a document type, adding content, and designing a view for a registration page in Umbraco. By the end of this tutorial, you will have a fully functional registration page integrated into your Umbraco site.

Prerequisites

Before you begin, ensure that your system meets the following requirements:

  • An Umbraco project.
  • Development Environment: Visual Studio or any other C# IDE.
  • Database: SQL Server, SQLite, or any supported database.

Step 1: Creating the Document Type for registration page

The first step in creating a registration page is to set up a document type. A document type in Umbraco acts as a blueprint for the content you want to create.

  1. Navigate to the Settings Section: In the Umbraco backoffice, go to the “Settings” section.
  2. Create a New Document Type: Click the + sign next to “Document Types” and select “Document Type with Template”. Name your document type (e.g., “Register”).
  3. Click on “Save” button.
  4. Define the structure: Edit the structure of your home page and add to the “Allowed child node types” property the “Register” document type.

Step 2: Adding Content for registration page

Once your document type is set up, you can add content to your registration page.

  1. Navigate to the Content Section: Go to the “Content” section in the Umbraco backoffice.
  2. Create a New Page: Click the + icon next to the Home page and select the “Register” document type we created earlier.
  3. Fill in the Properties: Enter the name of the page (e.g., “Register”).
  4. Click on “Save and publish” button.

Step 3: Designing the View for registration page

The final step is to create a view to display the registration page on your website.

  1. Locate the template: In the “Settings” section, click the arrow next on “Templates” to display the templates.
  2. Edit the template in one of the following ways:
    • Open the template by clicking on it’s name and add the necessary HTML and Razor code to render the registration form.
    • We use Visual Studio or any other text editor we wish to edit the "register.cshtml" file which is located in the "Views" folder of the Umbraco installation.

Below is a basic example for a registration page.

@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage

@using Microsoft.AspNetCore.WebUtilities
@using System.Text
@using Microsoft.Extensions.Options
@using Umbraco.Cms.Core.Configuration.Models
@using Umbraco.Cms.Core.Mail
@using Umbraco.Cms.Core.Security
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Web.Common
@using Umbraco.Cms.Web.Common.Security
@using Umbraco.Cms.Core.Models

@inject IMemberManager memberManager
@inject IMemberSignInManager memberSignInManager
@inject IMemberService memberService
@inject IEmailSender emailSender
@inject IOptions<GlobalSettings> globalSettings
@inject UmbracoHelper umbracoHelper

@{
    Layout = null;

    IPublishedContent? home = umbracoHelper.ContentAtRoot().FirstOrDefault();

    IPublishedContent? login = home?.Children<IPublishedContent>()?.Where(m => m.ContentType.Alias == "login").FirstOrDefault();

    IPublishedContent? registerConfirmation = home?.Children<IPublishedContent>()?.Where(m => m.ContentType.Alias == "registerConfirmation").FirstOrDefault();

    IPublishedContent? confirmEmail = home?.Children<IPublishedContent>()?.Where(m => m.ContentType.Alias == "confirmEmail").FirstOrDefault();

    string displayName = "";
    string displayNameError = "";
    string firstName = "";
    string firstNameError = "";
    string lastName = "";
    string lastNameError = "";
    string email = "";
    string emailError = "";
    string password = "";
    string passwordError = "";
    string confirmPassword = "";
    string confirmPasswordError = "";

    if (Context.Request.Method == "POST")
    {
        bool errorFound = false;

        displayName = Context.Request.Form["displayName"].ToString().Trim();
        firstName = Context.Request.Form["firstName"].ToString().Trim();
        lastName = Context.Request.Form["lastName"].ToString().Trim();
        email = Context.Request.Form["email"].ToString().Trim().ToLower();
        password = Context.Request.Form["password"].ToString().Trim();
        confirmPassword = Context.Request.Form["confirmPassword"].ToString().Trim();

        if (string.IsNullOrEmpty(displayName))
        {
            displayNameError = "Display name is a required field";
            errorFound = true;
        }

        if (string.IsNullOrEmpty(firstName))
        {
            firstNameError = "First name is a required field";
            errorFound = true;
        }

        if (string.IsNullOrEmpty(lastName))
        {
            lastNameError = "Last name is a required field";
            errorFound = true;
        }

        if (string.IsNullOrEmpty(email))
        {
            emailError = "Email is a required field";
            errorFound = true;
        }
        else if (!System.Net.Mail.MailAddress.TryCreate(email, out System.Net.Mail.MailAddress? addr))
        {
            emailError = "Email is not valid";
            errorFound = true;
        }

        if (string.IsNullOrEmpty(password))
        {
            passwordError = "Password is a required field";
            errorFound = true;
        }

        if (string.IsNullOrEmpty(confirmPassword))
        {
            confirmPasswordError = "Confirm password is a required field";
            errorFound = true;
        }
        else if (confirmPassword != password)
        {
            confirmPasswordError = "Confirm password and Password do not match";
            errorFound = true;
        }

        if (!errorFound)
        {
            Umbraco.Cms.Core.Security.MemberIdentityUser user = new Umbraco.Cms.Core.Security.MemberIdentityUser();
            user.Name = displayName;
            user.Email = email;
            user.UserName = email;
            user.IsApproved = true;
            user.EmailConfirmed = false;
            var result = await memberManager.CreateAsync(user, password);

            if (result.Succeeded)
            {
                IMember? member = memberService.GetByKey(user.Key);

                if (member == null)
                {
                    throw new InvalidOperationException($"Could not find a member with key.");
                }

                if (member.Properties.Contains("firstName"))
                    member.Properties["firstName"]?.SetValue(firstName);
                if (member.Properties.Contains("lastName"))
                    member.Properties["lastName"]?.SetValue(lastName);

                memberService.Save(member);

                MemberIdentityUser? member2 = await memberManager.FindByEmailAsync(email);

                if (member2 == null)
                {
                    // Don't reveal that the user does not exist or is not confirmed
                    Context.Response.Redirect(registerConfirmation!.Url());
                }
                else
                {
                    var code = await memberManager.GenerateEmailConfirmationTokenAsync(member2);
                    code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));

                    string callbackUrl = $"{confirmEmail!.Url(mode: UrlMode.Absolute)}?userID={System.Net.WebUtility.UrlEncode(member.Id.ToString())}&code={System.Net.WebUtility.UrlEncode(code)}";
  
                    try
                    {
                        string? fromAddress = globalSettings.Value.Smtp?.From;
                        if (!string.IsNullOrWhiteSpace(fromAddress))
                        {
                            string subject = "Confirm your email";
                            string body = $"Please confirm your account by <a href='{System.Web.HttpUtility.HtmlEncode(callbackUrl)}'>clicking here</a>.";
                            Umbraco.Cms.Core.Models.Email.EmailMessage message = new Umbraco.Cms.Core.Models.Email.EmailMessage(fromAddress, email, subject, body, true);
                            await emailSender.SendAsync(message, "Contact");
                        }
                    }
                    catch (Exception) { }
                }

                Context.Response.Redirect(registerConfirmation!.Url());
            }
            else if (result.Errors.First().Code == "DuplicateUserName")
            {
                emailError = $"The email already exists";
            }
            else if (result.Errors.First().Code == "PasswordTooShort")
            {
                emailError = $"Password too short";
            }
            else
            {
                emailError = result.Errors.First().Code;
            }
        }
    }
}

<html>
<head>
    <title>Registration Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Registration Page</h1>
        <hr />
        <form method="post">
            <div class="row mb-3">
                <div class="col-md-12">
                    <label for="displayName" class="form-label">Display Name</label>
                    <input type="text" id="displayName" name="displayName" value="@displayName" class="form-control" placeholder="Display Name">
                    <p class="text-danger">@displayNameError</p>
                </div>
            </div>
            <div class="row mb-3">
                <div class="col-md-6">
                    <label for="firstName" class="form-label">First Name</label>
                    <input type="text" id="firstName" name="firstName" value="@firstName" class="form-control" placeholder="First Name">
                    <p class="text-danger">@firstNameError</p>
                </div>
                <div class="col-md-6">
                    <label for="lastName" class="form-label">Last Name</label>
                    <input type="text" id="lastName" name="lastName" value="@lastName" class="form-control" placeholder="Last Name">
                    <p class="text-danger">@lastNameError</p>
                </div>
            </div>
            <div class="row mb-3">
                <div class="col-md-12">
                    <label for="email" class="form-label">Email</label>
                    <input type="text" id="email" name="email" value="@email" class="form-control" placeholder="Email">
                    <p class="text-danger">@emailError</p>
                </div>
            </div>
            <div class="row mb-3">
                <div class="col-md-6">
                    <label for="password" class="form-label">Password</label>
                    <input type="password" id="password" name="password" value="@password" class="form-control" placeholder="Password">
                    <p class="text-danger">@passwordError</p>
                </div>
                <div class="col-md-6">
                    <label for="confirmPassword" class="form-label">Confirm Password</label>
                    <input type="password" id="confirmPassword" name="confirmPassword" value="@confirmPassword" class="form-control" placeholder="Confirm Password">
                    <p class="text-danger">@confirmPasswordError</p>
                </div>
            </div>
            <div class="row mb-3">
                <div class="col-md-6">
                    <button type="submit" class="btn btn-primary">Register</button>
                </div>
            </div>
            <p><a href="@login?.Url()">Login</a></p>
        </form>
    </div>

</body>
</html>

Step 4: Creating the Document Type for registration confirmation page

After the user is registered we should go to the registration confirmation page to inform the user of their successful registration. Let's start by creating the document type for this page.

  1. Navigate to the Settings Section: In the Umbraco backoffice, go to the “Settings” section.
  2. Create a New Document Type: Click the + sign next to “Document Types” and select “Document Type with Template”. Name your document type (e.g., “Register Confirmation”).
  3. Click on “Save” button.
  4. Define the structure: Edit the structure of your home page and add to the “Allowed child node types” property the “Register Confirmation” document type.

Step 5: Adding Content for registration confirmation page

Once your document type is set up, you can add content to your registration confirmation page.

  1. Navigate to the Content Section: Go to the “Content” section in the Umbraco backoffice.
  2. Create a New Page: Click the + icon next to the Home page and select the “Registration Confirmation” document type we created earlier.
  3. Fill in the Properties: Enter the name of the page (e.g., “Register Page”).
  4. Click on “Save and publish” button.

Step 6: Designing the View for registration confirmation page

The final step is to create a view to display the registration confirmation page on your website.

  1. Locate the template: In the “Settings” section, click the arrow next on “Templates” to display the templates.
  2. Edit the template in one of the following ways:
    • Open the template by clicking on it’s name and add the necessary HTML and Razor code to render the registration confirmation page.
    • We use Visual Studio or any other text editor we wish to edit the "registerConfirmation.cshtml" file which is located in the "Views" folder of the Umbraco installation.

Below is a basic example for a registration confirmation page.

@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage

@using Umbraco.Cms.Web.Common
@inject UmbracoHelper umbracoHelper

@{
    Layout = null;

    IPublishedContent? home = umbracoHelper.ContentAtRoot().FirstOrDefault();

    IPublishedContent? login = home?.Children<IPublishedContent>()?.Where(m => m.ContentType.Alias == "login").FirstOrDefault();
}

<html>
<head>
    <title>Registration Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Registration Page</h1>
        <hr />
        <p>Please check your emails in order to confirm your account</p>
        <a href="@login?.Url()" class="btn">Login</a>
    </div>
</body>
</html>

Step 7: Creating the Document Type for email confirmation page

During the member's registration, an e-mail message is sent containing a hyperlink through which the member can confirm that he is the owner of the e-mail address he provided during registration. For this reason we will have to create a new document type to confirm the email address.

  1. Navigate to the Settings Section: In the Umbraco backoffice, go to the “Settings” section.
  2. Create a New Document Type: Click the + sign next to “Document Types” and select “Document Type with Template”. Name your document type (e.g., “Confirm Email”).
  3. Click on “Save” button.
  4. Define the structure: Edit the structure of your home page and add to the “Allowed child node types” property the “Register Confirmation” document type.

Step 8: Adding Content for email confirmation page

Once your document type is set up, you can add content to your registration confirmation page.

  1. Navigate to the Content Section: Go to the “Content” section in the Umbraco backoffice.
  2. Create a New Page: Click the + icon next to the Home page and select the “Confirm Email” document type we created earlier.
  3. Fill in the Properties: Enter the name of the page (e.g., “Email Confirmation Page”).
  4. Click on “Save and publish” button.

Step 9: Designing the View for email confirmation page

The final step is to create a view to display the email confirmation page on your website.

  1. Locate the template: In the “Settings” section, click the arrow next on “Templates” to display the templates.
  2. Edit the template in one of the following ways:
    • Open the template by clicking on it’s name and add the necessary HTML and Razor code to render the registration confirmation page.
    • We use Visual Studio or any other text editor we wish to edit the "confirmEmail.cshtml" file which is located in the "Views" folder of the Umbraco installation.

Below is a basic example for a email confirmation page.

@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage

@using Umbraco.Cms.Web.Common
@using Microsoft.AspNetCore.WebUtilities
@using System.Text
@using Umbraco.Cms.Core.Security

@inject IMemberManager memberManager
@inject UmbracoHelper umbracoHelper

@{
    Layout = null;

    IPublishedContent? home = umbracoHelper.ContentAtRoot().FirstOrDefault();

    IPublishedContent? login = home?.Children<IPublishedContent>()?.Where(m => m.ContentType.Alias == "login").FirstOrDefault();

    string userID = Context.Request.Query["userID"].ToString();
    string code = Context.Request.Query["code"].ToString();
    code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));

    string errorMessage = "";
    if (string.IsNullOrWhiteSpace(userID) || string.IsNullOrWhiteSpace(code))
    {
        errorMessage = "Error confirming your email.";
    }
    else
    {
        Umbraco.Cms.Core.Security.MemberIdentityUser? member = await memberManager.FindByIdAsync(userID);
        if (member == null)
        {
            errorMessage = "Error confirming your email.";
        }
        else
        {
            var result = await memberManager.ConfirmEmailAsync(member, code);
            if (!result.Succeeded)
            {
                errorMessage = "Error confirming your email.";
            }
        }
    }
}

<html>
<head>
    <title>Email Confirmation Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Email Confirmation Page</h1>
        <hr />
        @if (!string.IsNullOrWhiteSpace(errorMessage))
        {
            <p class="text-danger">@errorMessage</p>
        }
        else
        {
            <p>Thank you for confirming your email.</p>
        }
        <a href="@login?.Url()" class="btn">Login</a>
    </div>
</body>
</html>

Step 10: Specify Umbraco's SMTP settings

So far we have built the three pages we need to have a member registration process including checking to confirm that the email address the member specified is valid. But for this to happen we will need to configure Umbraco's SMTP settings so that it can send email messages.

To be able to do this, we should edit the appsettings.json file and add the following Smtp section to it, setting valid values for the SMTP server we want to use.

{
    "Umbraco": {
        "CMS": {
            "Global": {
                "Smtp": {
                    "From": "<your email>",
                    "Host": "<host>",
                    "Port": <port>,
                    "PickupDirectoryLocation": "<optional directory>",
                    "Username": "<optional username>",
                    "Password": "<optional password>",
                    "DeliveryMethod": "<Network(default)|SpecifiedPickupDirectory|PickupDirectoryFromIis>",
                    "SecureSocketOptions": "<None|Auto(default)|SslOnConnect|StartTls|StartTlsWhenAvailable>"
                }
            }
        }
    }
}

Conclusion

By following these steps, you have successfully created a registration page in Umbraco. This registration page can now be integrated into your website, providing users with a seamless registration experience.