---
title: Deploying objects with custom ID fields
related:
  - https://docs.kentico.com/13/deploying-websites/exporting-and-importing-sites.md
  - https://docs.kentico.com/13/deploying-websites/content-staging.md
  - https://docs.kentico.com/13/custom-development/handling-global-events.md
  - https://docs.kentico.com/13/custom-development/handling-global-events/reference-global-system-events.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).

When transferring data between instances of Xperience (via [import/export](https://docs.kentico.com/13/deploying-websites/exporting-and-importing-sites.md) or [staging](https://docs.kentico.com/13/deploying-websites/content-staging.md)), the IDs of objects can differ between the environments. Xperience automatically "translates" the ID values for system objects, but not for custom objects. For example, when you stage data of a [custom table](https://docs.kentico.com/13/developing-websites/defining-website-content-structure/managing-custom-tables.md) or [page type](https://docs.kentico.com/13/developing-websites/defining-website-content-structure/managing-page-types.md) that contains a custom field storing object IDs, the values may not match the IDs of the objects on the target server.

You can ensure that the system correctly translates custom ID fields by handling the events in the **ColumnsTranslationEvents** class:

- **RegisterRecords** – occurs on the source application when exporting objects. Handle this event to provide information for custom field translation.
- **TranslateColumns** – occurs on the target application when importing objects. Handle this event to translate field values using the provided information.

> **Note:** **Important**
>
> Handle the _RegisterRecords_ event on the  _**source**_  application, and the _TranslateColumns_ event on the  _**target**_  application. Add the handlers to both applications to ensure correct ID translation for both directions (e.g., in bi-directional staging environments).

### Example

The following example demonstrates how to implement custom ID translation for the _CustomTableUserID_ field of a [custom table](https://docs.kentico.com/13/developing-websites/defining-website-content-structure/managing-custom-tables.md). The field stores the IDs of the users who own individual records in the custom table.

1. Open your Xperience administration solution in Visual Studio (using the **WebApp.sln** file).
2. Create a [custom module class](https://docs.kentico.com/13/custom-development/creating-custom-modules/initializing-modules-to-run-custom-code.md).
   - Add the class into a custom _Class Library_ project within the solution.
3. Override the module's **OnInit** method and assign a handlers to the **ColumnsTranslationEvents.RegisterRecords.Execute** and **ColumnsTranslationEvents.TranslateColumns.Execute** events.

   ```csharp

   using CMS;
   using CMS.DataEngine;
   using CMS.CustomTables;
   using CMS.Helpers;
   using CMS.Membership;

   // Registers the custom module into the system
   [assembly: RegisterModule(typeof(CustomIDTranslationModule))]

   public class CustomIDTranslationModule : Module
   {
       // Module class constructor, the system registers the module under the name "CustomIDTranslation"
       public CustomIDTranslationModule()
           : base("CustomIDTranslation")
       {
       }    

       // Contains initialization code that is executed when the application starts
       protected override void OnInit()
       {
           base.OnInit();

           // Add this code on the SOURCE application from which you are exporting the objects
           // Assigns a handler method to the RegisterRecords event
           ColumnsTranslationEvents.RegisterRecords.Execute += RegisterRecords_Execute;

           // Add this code on the TARGET application where you are importing the objects
           // Assigns a handler method to the TranslateColumns event
           ColumnsTranslationEvents.TranslateColumns.Execute += TranslateColumns_Execute;
       }
   }

   ```
4. Define the handler methods (inside the custom module class):

   ```csharp

   // Provides the ID translation data when exporting objects
   private void RegisterRecords_Execute(object sender, ColumnsTranslationEventArgs e)
   {
       // Registers custom column translation data for "customtable.sampletable"
       if (e.ObjectType == CustomTableItemProvider.GetObjectType("customtable.sampletable"))
       {
           // Gets the user ID from the custom table's data
           int userId = ValidationHelper.GetInteger(e.Data.GetValue("CustomTableUserID"), 0);

           // Prepares parameters for the translation
           TranslationParameters parameters = new TranslationParameters(UserInfo.OBJECT_TYPE)
           {
               CodeName = UserInfoProvider.GetUserNameById(userId)
           };

           // Maps the user ID value to the corresponding username for every record in the custom table's data
           // Adds the mapping information into the export package
           e.TranslationHelper.RegisterRecord(userId, parameters);
       }
   }

   // Handles ID translation when importing objects
   private void TranslateColumns_Execute(object sender, ColumnsTranslationEventArgs e)
   {
       // Performs column translation for "customtable.sampletable"
       if (e.ObjectType == CustomTableItemProvider.GetObjectType("customtable.sampletable"))
       {
           // Translates the values of the UserID field in the table's data
           // Uses the mapping information in the import package to find the correct IDs based on the usernames
           e.TranslationHelper.TranslateColumn(e.Data, "CustomTableUserID", UserInfo.OBJECT_TYPE, 0, true, true);
       }
   }

   ```
5. Save the class and Rebuild the solution.

When you transfer the custom table's data between the applications using import/export or content staging, the handlers ensure correct translation of ID values for the _CustomTableUserID_ field.
