---
title: Registering custom macro methods
related:
  - https://docs.kentico.com/13/macro-expressions/reference-macro-methods.md
  - https://docs.kentico.com/13/macro-expressions/macro-syntax.md
  - https://docs.kentico.com/13/macro-expressions/extending-the-macro-engine/creating-macro-namespaces.md
  - https://docs.kentico.com/13/macro-expressions/extending-the-macro-engine/adding-custom-macro-fields.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

In addition to the [default macro methods](https://docs.kentico.com/13/macro-expressions/reference-macro-methods.md), you can also create your own methods. Users can then run custom functionality by calling the methods inside macro expressions.

Use the following process to add macro methods into the system:

1. Define the methods inside a container class.
2. [Register your macro method container](#registering-macro-method-containers) for a certain object type or macro namespace.
3. Deploy the custom classes to both your Xperience administration project and the separate live site application. This ensures that the custom macro method can be resolved by both applications. For more information, see [Applying customizations in the Xperience environment](https://docs.kentico.com/13/custom-development/applying-customizations-in-the-xperience-environment.md).

## Defining macro methods

1. Open your project in Visual Studio.
2. [Add a custom assembly](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md) (_Class Library_ project) with class discovery enabled to the solution, or re-use an existing assembly.
3. Create a new class within the custom project.
4. Edit the class and add a _using_ statement for the **CMS.MacroEngine** namespace:

   ```csharp

   using CMS.MacroEngine;

   ```
5. Make the class inherit from **MacroMethodContainer**:

   ```csharp

   /// <summary>
   /// Sample MacroMethodContainer class.
   /// </summary>
   public class CustomMacroMethods : MacroMethodContainer
   {

   }

   ```
6. Define your methods inside the container class. Macro methods must always have the following signature:

   ```csharp

   public static object MyMethod(EvaluationContext context, params object[] parameters)


   ```

   > **Info:** The **EvaluationContext** parameter allows you to get information about the context in which the macro containing the method was resolved. For example, you can check the identity of the user in the [macro signature](https://docs.kentico.com/13/macro-expressions/troubleshooting-macros/working-with-macro-signatures.md) (for security purposes) or the values of [macro parameters](https://docs.kentico.com/13/macro-expressions/macro-syntax.md#macro-parameters), such as the culture or case sensitivity of string comparisons.
   >
   > The **parameters** array stores the method's parameters. When the system resolves the method, the values of the arguments pass into the array. You need to define individual parameters via attributes (see below).

   > **Note:** **Note**
   >
   > We strongly recommend that you ensure the following in the code of your methods:
   >
   > - **Caching** – if you load data in the method's code, use the [Xperience caching API](https://docs.kentico.com/13/configuring-xperience/configuring-caching/caching-in-custom-code.md) to optimize the performance.
   > - **Security** – you need to handle permissions and other security checks manually in the method's code to avoid security vulnerabilities. To build security conditions, get the _UserInfo_ object representing the user who entered the macro from the **User** property of the method's **EvaluationContext** parameter.
7. Add the **MacroMethod** attribute above the method declaration. Specify the following parameters for the attribute:

   - **Type** – the return type of the method.
   - **Comment** – comment displayed for the method in the macro autocomplete help.
   - **Minimum parameters** – the minimum number of parameters that must be specified when calling the method (minimum overload).
8. Add a **MacroMethodParam** attribute for each of the method's parameters. For every parameter, you must specify:

   - **Index number** (sets the index of the parameter in the _params_ array)
   - **Name**
   - **Data type**
   - **Comment** (appears in the macro autocomplete)

```csharp title="Example"

using CMS.MacroEngine;
using CMS.Helpers;

public class CustomMacroMethods : MacroMethodContainer
{
    [MacroMethod(typeof(string), "Combines two strings, or appends a culture suffix when called with one parameter.", 1)]
    [MacroMethodParam(0, "param1", typeof(string), "First part of the string.")]
    [MacroMethodParam(1, "param2", typeof(string), "Second part of the string (optional).")]
    public static object ConnectStrings(EvaluationContext context, params object[] parameters)
    {
        // Branches according to the number of the method's parameters
        switch (parameters.Length)
        {
            case 1:
                // Overload with one parameter
                return ValidationHelper.GetString(parameters[0], "") + " - Resolved in culture: " + context.Culture;

            case 2:
                // Overload with two parameters
                return ValidationHelper.GetString(parameters[0], "") + " - " + ValidationHelper.GetString(parameters[1], "");

            default:
                // No other overloads are supported
                throw new NotSupportedException();
        }
    }
}

```

## Registering macro method containers

After you [prepare your macro methods in a container class](#defining-macro-methods), register the container by extending an object type or macro namespace.

1. Edit the class containing your macro method container.
2. Add a **RegisterExtension** assembly attribute above the class declaration for each type that you wish to extend (requires a reference to the **CMS** namespace).

Specify the type parameters for the **RegisterExtension** attribute in the following format:

`[assembly: RegisterExtension(typeof(*\<macro method container class\>*), typeof(*\<extended type\>*))]`

You can extend the following types:

- General system types (string, int, ...)
- Xperience API object types (UserInfo, TreeNode, ...)
- [Macro namespaces](https://docs.kentico.com/13/macro-expressions/extending-the-macro-engine/creating-macro-namespaces.md) (SystemNamespace, StringNamespace, MathNamespace, ...)
- Custom types

```csharp title="Example"

using CMS;

using CMS.MacroEngine;
using CMS.Helpers;

// Makes all methods in the 'CustomMacroMethods' container class available for string objects
[assembly: RegisterExtension(typeof(CustomMacroMethods), typeof(string))]
// Registers methods from the 'CustomMacroMethods' container into the "String" macro namespace
[assembly: RegisterExtension(typeof(CustomMacroMethods), typeof(StringNamespace))]

public class CustomMacroMethods : MacroMethodContainer
{
...

```

## Result - Calling custom methods in macros

Once you have your custom macro methods implemented and registered, you can call them in macro expressions.

Open any macro code editor in the administration interface. The autocomplete help offers the new methods for the extended types or namespaces.

![Custom macro method appearing in the autocomplete of a string property](https://docs.kentico.com/docsassets/13/registering-custom-macro-methods/Custom_Macro_Method_Result.png "Custom macro method appearing in the autocomplete of a string property")

For example:

- Append the method to a macro object of the data type that you extended (_string_ in the sample code):

  ```text

  {% CurrentUser.UserName.ConnectStrings() %}
  ```

  > **Info:** The recommended K# syntax is to use infix notation for the first parameter of methods. You can call the method in the following forms:
  >
  > - **{% "String1".ConnectStrings("String2") %}** – recommended and supported by the [autocomplete help](https://docs.kentico.com/13/macro-expressions/entering-macro-expressions.md).
  > - **{% ConnectStrings("String1", "String2") %}**

– OR –

- Enter the extended macro namespace, and then call the method:

  ```text
  {% String.ConnectStrings("First part", "Second part") %}
  ```

## Macro method code samples

The Xperience installation includes code examples of custom macro method registration, which you can add directly to your web project.

Access the samples in your Xperience setup file directory (by default _C:\Program Files\Kentico\\_), under the _CodeSamples\CustomizationSamples\\_ sub-directory.

You can find the macro method examples in the following classes:

- **Macros/CustomMacroMethods.cs** – class containing the sample macro methods.
- **Modules/SampleMacroModule.cs** – initializes the custom method registration.
