Umbraco CMS
CloudHeartcoreDXPMarketplace
13.latest (LTS)
13.latest (LTS)
  • Umbraco CMS Documentation
  • Legacy Documentation
    • Umbraco 11 Documentation
    • Umbraco 8 Documentation
    • Umbraco 7 Documentation
  • Release Notes
  • Contribute
  • Sustainability Best Practices
  • Fundamentals
    • Get to know Umbraco
    • Setup
      • Requirements
      • Installation
        • Install using .NET CLI
        • Install using Visual Studio
        • Local IIS With Umbraco
        • Install using Visual Studio Code
        • Installing Nightly Builds
        • Running Umbraco on Linux/macOS
        • Unattended Installs
      • Upgrade your project
        • Version Specific Upgrades
          • Upgrade from Umbraco 8 to the latest version
          • Migrate content to Umbraco 8
          • Minor upgrades for Umbraco 8
          • Upgrade to Umbraco 7
          • Minor upgrades for Umbraco 7
      • Server setup
        • Running Umbraco On Azure Web Apps
        • Hosting Umbraco in IIS
        • File And Folder Permissions
        • Runtime Modes
        • Umbraco in Load Balanced Environments
          • Load Balancing Azure Web Apps
          • Standalone File System
          • Advanced Techniques With Flexible Load Balancing
          • Logging With Load Balancing
    • Backoffice
      • Sections
      • Property Editors
        • Built-in Property Editors
          • Checkbox List
          • Color Picker
          • Content Picker
          • DateTime
          • Date
          • Decimal
          • Email Address
          • Eye Dropper Color Picker
          • File Upload
          • Image Cropper
          • Label
          • List View
          • Markdown Editor
          • Media Picker
          • Media Picker (Legacy)
          • Member Group Picker
          • Member Picker
          • Multi Url Picker
          • Multinode Treepicker
          • Repeatable Textstrings
          • Numeric
          • Radiobutton List
          • Slider
          • Tags
          • Textarea
          • Textbox
          • Toggle
          • User Picker
          • Block Editors
            • Block Grid
            • Block List
            • Build a Custom View for a Block
            • Configuring Block Editor Label Properties
          • Dropdown
          • Grid Layout (Legacy)
            • What Are Grid Layouts?
            • Configuring The Grid Layout
            • Settings And Styling
            • Grid Editors
            • Build Your Own Editor
            • Rendering Grid In a Template
            • Grid Layout Best Practices
            • Add Values Programmatically
          • Rich Text Editor
            • Rich Text Editor Configuration
            • Rich Text Editor Styles
            • Rich Text Editor Plugins
            • Blocks in Rich Text Editor
      • Login
      • Content Templates
      • Infinite Editing
      • Log Viewer
      • Language Variants
      • Settings Dashboards
    • Data
      • Defining Content
        • Default Document Types
        • Document Type Localization
      • Creating Media
        • Default Data/Media Types
      • Members
      • Data Types
        • Default Data Types
      • Scheduled Publishing
      • Using Tabs
      • Users
      • Relations
      • Dictionary Items
      • Content Version Cleanup
    • Design
      • Templates
        • Basic Razor Syntax
        • Named Sections
        • Razor Cheatsheet
      • Rendering Content
      • Rendering Media
      • Partial Views
      • Partial View Macro Files
      • Stylesheets And JavaScript
    • Code
      • Service APIs
      • Subscribing To Notifications
      • Creating Forms
      • Debugging
        • Logging
      • Source Control
  • Implementation
    • Learn how Umbraco works
    • Routing
      • Controller & Action Selection
      • Execute Request
      • Request Pipeline
    • Custom Routing
      • Adding a hub with SignalR and Umbraco
    • Controllers
    • Data Persistence (CRUD)
    • Composing
    • Integration Testing
    • Nullable Reference Types
    • Services and Helpers
      • Circular Dependencies
    • Unit Testing
  • Extending
    • Customize the editing experience
    • Dashboards
    • Sections & Trees
      • Sections
      • Trees
        • Tree Actions
      • Searchable Trees (ISearchableTree)
    • Property Editors
      • Property Value Converters
      • Property Actions
      • Tracking References
      • Declaring your property editor
      • Content Picker Value Converter Example
    • Package Manifest
    • Macro Parameter Editors
    • Health Check
      • Health Check Guides
        • Click-Jacking Protection
        • Content/MIME Sniffing Protection
        • Cross-site scripting Protection (X-XSS-Protection header)
        • Debug Compilation Mode
        • Excessive Headers
        • Fixed Application Url
        • Folder & File Permissions
        • HTTPS Configuration
        • Macro Errors
        • Notification Email Settings
        • SMTP
        • Strict-Transport-Security Header
    • Language Files & Localization
    • Backoffice Search
    • Backoffice Tours
    • Backoffice UI API Documentation
    • Content Apps
    • Creating a Custom Database Table
    • Embedded Media Providers
    • Custom File Systems (IFileSystem)
      • Using Azure Blob Storage for Media and ImageSharp Cache
    • Configuring Azure Key Vault
    • Packages
      • Creating a Package
      • Language file for packages
      • Listing a Package on the Umbraco Marketplace
      • Good practice and defaults
      • Packages on Umbraco Cloud
      • Installing and Uninstalling Packages
      • Maintaining packages
      • Create accessible Umbraco packages
      • Example Package Repository
    • UI Library
  • Reference
    • Dive into the code
    • Configuration
      • Basic Authentication Settings
      • Connection strings settings
      • Content Dashboard Settings
      • Content Settings
      • Data Types Settings
      • Debug settings
      • Examine settings
      • Exception filter settings
      • FileSystemProviders Configuration
      • Global Settings
      • Health checks
      • Hosting settings
      • Imaging settings
      • Indexing settings
      • Install Default Data Settings
      • Keep alive settings
      • Logging settings
      • Maximum Upload Size Settings
      • Models builder settings
      • NuCache Settings
      • Package Migration
      • Plugins settings
      • Request handler settings
      • Rich text editor settings
      • Runtime minification settings
      • Runtime settings
      • Security Settings
      • Serilog settings
      • Tours settings
      • Type finder settings
      • Unattended
      • Web routing
    • Templating
      • Macros
        • Managing macros
        • Partial View Macros
      • Models Builder
        • Introduction
        • Configuration
        • Builder Modes
        • Understand and Extend
        • Using Interfaces
        • Tips and Tricks
      • Working with MVC
        • Working with MVC Views in Umbraco
        • View/Razor Examples
        • Using MVC Partial Views in Umbraco
        • Using View Components in Umbraco
        • Querying & Traversal
        • Creating Forms
    • Querying & Models
      • IMemberManager
      • IPublishedContentQuery
      • ITagQuery
      • UDI Identifiers
      • UmbracoContext helper
      • UmbracoHelper
      • IPublishedContent
        • IPublishedContent Collections
        • IPublishedContent IsHelpers
        • IPublishedContent Property Access & Extension Methods
    • Routing & Controllers
      • Routing requirements for backoffice authentication
      • Custom MVC controllers (Umbraco Route Hijacking)
      • Custom MVC Routes
      • Custom Middleware
      • URL Rewrites in Umbraco
      • Special Property Type aliases for routing
      • URL Redirect Management
      • Routing in Umbraco
        • FindPublishedContentAndTemplate()
        • IContentFinder
        • Inbound request pipeline
        • Outbound request pipeline
        • Published Content Request Preparation
      • Surface controllers
        • Surface controller actions
      • Umbraco API Controllers
        • Umbraco Api - Authorization
        • Umbraco Api - Routing & Urls
    • Content Delivery API
      • Custom property editors support
      • Extension API for querying
      • Media Delivery API
      • Protected content in the Delivery API
      • Output caching
      • Property expansion and limiting
      • Additional preview environments support
    • Webhooks
      • Expanding Webhook Events
    • API versioning and OpenAPI
    • Searching
      • Examine
        • Examine Management
        • Examine Manager
        • Custom indexing
        • PDF indexes and multisearchers
        • Quick-start
    • Using Notifications
      • Notification Handler
      • CacheRefresher Notifications Example
      • ContentService Notifications Example
      • Creating And Publishing Notifications
      • Determining if an entity is new
      • MediaService Notifications Example
      • MemberService Notifications Example
      • Sending Allowed Children Notification
      • Umbraco Application Lifetime Notifications
      • EditorModel Notifications
        • Customizing the "Links" box
      • Hot vs. cold restarts
    • Inversion of Control / Dependency injection
    • Management
      • Models Reference
        • Content
        • ContentType
        • DataType
        • DictionaryItem
        • Language
        • Media
        • MediaType
        • Relation
        • RelationType
        • ServerRegistration
        • Template
      • Services Reference
        • AuditService
        • ConsentService
        • DataTypeService
        • DomainService
        • EntityService
        • ExternalLoginService
        • FileService
        • MacroService
        • MediaService
        • MemberGroupService
        • MemberService
        • MemberTypeService
        • NotificationService
        • PackagingService
        • PublicAccessService
        • RedirectUrlService
        • RelationService
        • ServerRegistrationService
        • TagService
        • TextService
        • ContentService
          • Create content programmatically
          • Publish content programmatically
        • ContentTypeService
          • Retrieving content types
          • Retrieving content types
        • LocalizationService
          • Retrieving languages
        • UserService
          • Creating a user
    • Plugins
      • Creating Resolvers
      • Finding types
    • Cache & Distributed Cache
      • Accessing the cache
      • ICacheRefresher
      • IServerMessenger
      • Getting/Adding/Updating/Inserting Into Cache
      • Examples
        • Working with caching
    • Response Caching
    • Security
      • API rate limiting
      • BackOfficeUserManager and Events
      • Cookies
      • Replacing the basic username/password check
      • External login providers
      • Locking of Users and password reset
      • Reset admin password
      • Umbraco Security Hardening
      • Umbraco Security Settings
      • Sensitive data
      • Sanitizing the Rich Text Editor
      • Setup Umbraco for a FIPS Compliant Server
      • HTTPS
      • Two-factor Authentication
      • Server-side file validation
    • Scheduling
    • Common Pitfalls & Anti-Patterns
    • API Documentation
    • Debugging with SourceLink
    • Language Variation
    • UmbracoMapper
    • Distributed Locks
    • AngularJS
      • Directives
        • umbLayoutSelector
        • umbLoadIndicator
        • umbProperty
      • Services
        • Editor Service
        • Events Service
          • changeTitle
  • Tutorials
    • Overview
    • Creating a Basic Website
      • Getting Started
      • Document Types
      • Creating Your First Template
      • CSS and Images
      • Displaying the Document Type Properties
      • Creating a Master Template
      • Creating Pages and Using the Master Template
      • Setting the Navigation Menu
      • Articles and Article Items
      • Adding Language Variants
      • Conclusions
    • Creating a Custom Dashboard
      • Extending the Dashboard using the Umbraco UI library
    • Creating a Property Editor
      • Adding configuration to a property editor
      • Integrating services with a property editor
      • Adding server-side data to a property editor
    • Creating a Multilingual Site
    • Add Google Authentication (Users)
    • Add Microsoft Entra ID authentication (Members)
    • Creating a Backoffice Tour
    • Creating Custom Database Tables with Entity Framework
    • The Starter Kit
      • Lessons
        • Customize the Starter Kit
        • Add a Blog Post Publication Date
          • Add a Blog Post Publication Date
          • Add a Blog Post Publication Date
        • Add Open Graph
          • Add Open Graph - Step 1
          • Add Open Graph - Step 2
          • Add Open Graph - Step 3
          • Add Open Graph - Step 4
          • Add Open Graph - Summary
        • Ask For Help and Join the Community
    • Editor's Manual
      • Getting Started
        • Logging In and Out
        • Umbraco Interface
        • Creating, Saving and Publishing Content Options
        • Finding Content
        • Editing Existing Content
        • Sorting Pages
        • Moving a Page
        • Copying a Page
        • Deleting and Restoring Pages
      • Working with Rich Text Editor
      • Version Management
        • Comparing Versions
        • Rollback to a Previous Version
      • Media Management
        • Working with Folders
        • Working with Media Types
        • Cropping Images
      • Tips & Tricks
        • Refreshing the Tree View
        • Audit Trail
        • Notifications
        • Preview Pane Responsive View
        • Session Timeout
    • Multisite Setup
    • Member Registration and Login
    • Custom Views for Block List
    • Connecting Umbraco Forms and Zapier
    • Creating an XML Sitemap
    • Implementing Custom Error Pages
Powered by GitBook
On this page
  • Accessing the IUmbracoMapper
  • Mapping
  • Defining mappings
  • Context
  • Umbraco.Code
  • Full example
Edit on GitHub
Export as PDF
  1. Reference

UmbracoMapper

PreviousLanguage VariationNextDistributed Locks

Last updated 11 months ago

Often in code there is a need to 'map' one object's properties to another type of object. The 'type of objects' are not related by inheritance or interface. (Think database layer object, passing information to a presentation layer ViewModel etc). In these circumstances, it can save time and provide consistency to consolidate the logic to map between the options into one set of 'Mapping' rules.

UmbracoMapper replaced AutoMapper which was an external dependency. AutoMapper builds the mapping code dynamically, based upon mapping profiles, which are defined as C# expressions. UmbracoMapper relies on static code, that is, mappings need to be hand-written.

This is not to be confused with the of the same name.

UmbracoMapper was originally introduced to solve some issues in the Umbraco core code. However, it is fine for anyone to use in their custom site implementations or packages as they wish.

Accessing the IUmbracoMapper

The IUmbracoMapper is registered with Dependency Injection (DI). It can therefore be injected into constructors of controllers, custom classes etc, wherever DI is used.

Mapping

Mapping with the UmbracoMapper works in ways similar to AutoMapper:

// assuming source is ISource, create a new target instance
var target = umbracoMapper.Map<ITarget>(source);

// assuming both source and target already exists
target = umbracoMapper.Map(source, target);

The UmbracoMapper class also defines explicit methods to map enumerables:

// assuming sources is IEnumerable<ISource>, map to IEnumerable<ITarget>
var targets = umbracoMapper.MapEnumerable<ISource, ITarget>(sources);

Explicit mapping of enumerables enumerates the source items, and map each item individually.

It can also implicitly map enumerables. The following code is also valid:

// assuming sources is IEnumerable<ISource>, map to IEnumerable<ITarget>
var targets = umbracoMapper.Map<IEnumerable<ITarget>>(sources);

If a mapping has been defined from IEnumerable<ISource> to IEnumerable<ITarget>, then it will be used. Otherwise, the UmbracoMapper will look for a mapping from the source type to the target type, pretty much like the explicit method.

Defining mappings

Mappings are defined in IMapDefinition instances. This interface defines one method:

void DefineMaps(IUmbracoMapper mapper);
builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
    .Add<MyMapDefinition>();

A definition provides a constructor, and a map:

public void DefineMaps(IUmbracoMapper mapper)
{
    mapper.Define<ISource, ITarget>(
        (source, context) => { ... },           // constructor
        (source, target, context) => { .... }   // map
    );
}

The constructor function is used to create an instance of the target class. The most basic implementation would be:

(source, context) => new TargetClass(),

The mapping action is used to map an instance of the source class, to an instance of the target class. The most basic implementation would be:

(source, target, context) =>
{
    target.MyProperty1 = source.MyProperty1;
    target.MyProperty2 = source.MyProperty2;
    ...
}

The constructor function is used whenever the mapper is asked to create a target instance. Then, the mapping action is used.

In other words, umbracoMapper.Map<ITarget>(source) will first run the construction function, and then the mapping action. On the other hand, umbracoMapper.Map(source, target) where target already exists, would only run the mapping action.

The UmbracoMapper class provides multiple overloads of the Define method:

  • An overload accepting a constructor function and a mapping action, as presented above.

  • An overload accepting a mapping action only, which tells the mapper how to map to an existing target (but the mapper will not be able to create new target instances).

  • An overload accepting a construction function, which tells the mapper how to create new target instances (but the mapper will not perform any additional mapping).

  • A parameter-less overload, which defines a "no-operation" mapping (the mapper cannot create new target instance, and mapping does nothing).

Context

Both constructor functions and map actions presented above expose a context parameter which is an instance of MapperContext and provides two types of services:

  • An Items dictionary which can store any type of object, using string keys, and can be used to carry some context along mappings;

  • Some Map and MapEnumerable functions that can be used in mapping functions, to recursively map nested elements, while propagating the context.

The context provides a HasItem property. To check whether the context has items, without allocating an extra empty dictionary, use this property.

The context is used, for instance, to carry the culture when mapping content items with variants. See the MapperContextExtensions class, which contains methods such as:

public static void SetCulture(this MapperContext context, string culture)
{
    context.Items[CultureKey] = culture;
}

And

public static string GetCulture(this MapperContext context)
{
    return context.HasItems &&
            context.Items.TryGetValue(CultureKey, out var obj) &&
            obj is string s
        ? s
        : null;
}

Every Map and MapEnumerable method exposed by the UmbracoMapper have overloads that can manipulate the context before executing the mapping. For instance,

var target = umbracoMapper.Map<ITarget>(source, context =>
    {
        context.SetCulture(cultureName);
    });

Umbraco.Code

Umbraco.Code is an assembly which should contain coding utilities for Umbraco. At the moment, it contains only one Roslyn analyzer, the MapAllAnalyzer, which is used to help writing mapping methods.

The analyzer examines every method mapping from a source to a target, and being marked with the // Umbraco.Code.MapAll comment block:

mapper.Define<ISource, ITarget>(
        (source, context) => new Target(),  // constructor
        Map                                 // map
    );

// Umbraco.Code.MapAll
private static void Map(ISource source,
                        ITarget target,
                        MapperContext context)
{
    target.Property1 = source.Property1;
    target.Property2 = source.Property2;
}

The analyzer verifies that every publicly settable property of target is assigned a value. If a property is not assigned a value, the tool raises a build error (ie. the code will not compile).

Since, contrary to AutoMapper, mapping is not implicit nor automatic, this ensures that an error would be raised. Should a new property be added to ISource, the corresponding mappings must be updated.

It is possible to exclude some properties from the check:

// Umbraco.Code.MapAll -Property2

And the comment can be repeated if the list of excluded properties is long:

// Umbraco.Code.MapAll -Property2 -Property3 -Property4
// Umbraco.Code.MapAll -Property5 -Property6 -Property7

The analyzer follows the standard analyzer development patterns, and building the code in Release mode produces the appropriate NuGet package.

Full example

Below you will find a full example showing you how to map a collection of type Product to a collection of type ProductDto.

#region Models

public class Product
{
    public string Name { get; set; }
    public string SuperSecretThingNotForPublicDisplay { get; set; }
}

[DataContract(Name = "product")]
public class ProductDto
{
    [DataMember(Name = "name")]
    public string Name { get; set; }
}

#endregion

#region Mapping

public class ProductMappingDefinition : IMapDefinition
{
    public void DefineMaps(IUmbracoMapper mapper)
    {
        mapper.Define<Product, ProductDto>((source, context) => new ProductDto(), Map);
    }

    private void Map(Product source, ProductDto target, MapperContext context)
    {
        target.Name = source.Name;
    }
}

#endregion

#region Composing

public class ProductComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
    {
        builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
            .Add<ProductMappingDefinition>();
    }
}

#endregion

public class ProductsController : UmbracoApiController
{
    private readonly IUmbracoMapper _mapper;

    public ProductsController(IUmbracoMapper mapper) => _mapper = mapper;

    [HttpGet]
    public HttpResponseMessage GetAll()
    {
        var products = FakeServiceCall();
        var mapped = _mapper.MapEnumerable<Product, ProductDto>(products);

        return Request.CreateResponse(HttpStatusCode.OK, mapped);
    }

    [HttpGet]
    public HttpResponseMessage GetFirstProduct()
    {
        var product = FakeServiceCall().First();
        var mapped = _mapper.Map<ProductDto>(product);

        return Request.CreateResponse(HttpStatusCode.OK, mapped);
    }

    private IEnumerable<Product> FakeServiceCall()
    {
        return new List<Product>()
        {
            new Product()
            {
                Name = "Umbraco Cloud",
                SuperSecretThingNotForPublicDisplay = "Secret"
            },
            new Product()
            {
                Name = "Umbraco Forms",
                SuperSecretThingNotForPublicDisplay = "Also secret"
            }
        };
    }
}

Result from /umbraco/api/products/getall:

[
    {
        "name": "Umbraco Cloud"
    },
    {
        "name": "Umbraco Forms"
    }
]

Result from /umbraco/api/products/getfirstproduct:

{
    "name": "Umbraco Cloud"
}

Mappings are registered (and must be registered) via a :

The code lives in the and the tool is available via . It is included as a development dependency in Umbraco.

UmbracoMapper package by Andy Butland
Umbraco.Code repository
Nuget
collection builder