DEV Community

Cover image for A practical guide to relative paths on solution mapping files
Riccardo Gregori
Riccardo Gregori

Posted on

A practical guide to relative paths on solution mapping files

Every time I start a new Dataverse project, I find myself struggling to remember the exact syntax and structure of mapping files. Yet, these files are absolutely essential for proper Application Lifecycle Management (ALM). Without them, you'll end up with duplicated source code in your repository, broken builds, and a messy development workflow.

So I'm writing this as a personal referenceโ€”a memento I can return to whenever I need to set up mapping files correctly. If you're reading this and facing the same challenge, hopefully it helps you too.

๐Ÿ—๏ธ Project Structure Overview

The typical folder organization I use for my Dataverse projects is the following:

๐Ÿ“‚ ... other folders such as .github, .vscode, docs ...
๐Ÿ“‚ solutions
   ๐Ÿ“‚ master
      ๐Ÿ“‚ src
         ๐Ÿ“‚ ...solution components folders...
      ๐Ÿ“„ map.xml
      ๐Ÿ“„ master.cdsproj
๐Ÿ“‚ src
   ๐Ÿ“‚ Plugins
      ๐Ÿ“„ ...
   ๐Ÿ“‚ WebResources
      ๐Ÿ“‚ ava_
         ๐Ÿ“‚ images
         ๐Ÿ“‚ pages
         ๐Ÿ“‚ scripts
๐Ÿ“‚ ... other folders such as test ...
Enter fullscreen mode Exit fullscreen mode

This structure separates concerns effectively:

  • solutions/: Contains Dataverse solution definitions and metadata
  • src/: Houses source code for plugins, web resources, and other custom components

๐Ÿ“ฆ Understanding Solution Organization

The solutions folder contains a subfolder for each Dataverse solution I use in my project (can be 1 called master for simple projects, or more than one for moderately complex projects).

Each solution folder typically contains:

  • src/: Unpacked solution components (entities, forms, views, etc.)
  • map.xml: File mapping configuration (the focus of this post)
  • {solutionname}.cdsproj: MSBuild project file for the solution

๐Ÿ—บ๏ธ The Critical Role of Map.xml Files

For each solution containing WebResources or Plugin Packages/Plugin Assemblies, it is a best practice to create a map.xml file that can be used:

  • while running pac solution sync, to avoid storing in the repo twice the source code of WebResources, and the compiled .dll (or .nupkg) of a Plugin Assembly / Plugin Package
  • while running dotnet build to rebuild the solution, to instruct the solution package on where to retrieve the missing WebResources/Plugin Assemblies/Plugin Packages

๐Ÿค” Why Use Mapping Files?

Mapping files solve several critical problems in Dataverse development:

  1. Avoid Code Duplication: Without mapping, your repository would contain both source files (in src/) and processed files (in solutions/master/src/WebResources/), leading to redundancy and potential conflicts.

  2. Streamline Build Process: During dotnet build, the system knows exactly where to find source files to include in the solution package.

  3. Maintain Clean Repository: Source control focuses on actual source code rather than generated artifacts.

  4. Enable Automated Builds: CI/CD pipelines can reliably build solutions without manual intervention.

๐Ÿ” Anatomy of a Web Resources Map File

A typical map file for web resources looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Mapping>
    <!-- Map the web resources folder relative to the solutions\master\obj\debug\metadata\src\WebResources folder -->
    <FileToPath map="WebResources\**\*.png" to="..\..\..\..\..\src\WebResources\**" />
    <FileToPath map="WebResources\**\*.svg" to="..\..\..\..\..\src\WebResources\**" />
    <FileToPath map="WebResources\**\*.html" to="..\..\..\..\..\src\WebResources\**" />
    <FileToPath map="WebResources\**\*.js" to="..\..\..\..\..\src\WebResources\**" />
    <FileToPath map="WebResources\**\*.js.map" to="..\..\..\..\..\src\WebResources\**" />
    <FileToPath map="WebResources\**\*.xml" to="..\..\..\..\..\src\WebResources\**" />
</Mapping>
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฉ Breaking Down the Mapping Structure

Each <FileToPath> element defines a mapping rule:

  • map attribute: Specifies the pattern of files within the solution structure
  • to attribute: Defines where to find the actual source files
  • Wildcards (**): Allow recursive directory matching
  • File extensions: Target specific file types (.js, .html, .png, etc.)

๐Ÿ“ Common File Types to Map

The example above covers the most common web resource types:

  • .png/.svg: Image files for icons, logos, and graphics
  • .html: HTML pages and templates
  • .js/.js.map: JavaScript files and their source maps
  • .xml: Configuration files and metadata

You can extend this pattern for additional file types like CSS, JSON, or custom formats.

๐Ÿ”ข Understanding the Five Parent Directory Navigation (../)

The to part of the different types of mappings you can apply to a map.xml file is taken into consideration only during the build process.

dotnet build tries to rebuild the solution recreating all content of the src folder into the obj\Debug\Metadata folder.

Sample

This means that, in the mapping file, you must consider yourself to be within that folder when the actual mapping starts.

%base%\solutions\master\obj\Metadata\WebResources
โฌ‡๏ธ cd .. (1)
%base%\solutions\master\obj\Metadata
โฌ‡๏ธ cd .. (2)
%base%\solutions\master\obj
โฌ‡๏ธ cd .. (3)
%base%\solutions\master
โฌ‡๏ธ cd .. (4)
%base%\solutions
โฌ‡๏ธ cd .. (5)
%base%
โฌ‡๏ธ cd src\WebResources
%base%\src\WebResources
Enter fullscreen mode Exit fullscreen mode

๐Ÿ’ญ Final Thoughts

There you have itโ€”my personal cheat sheet for Dataverse mapping files. I hope that by writing this down, I'll finally stop second-guessing myself every time I start a new project. Those five ../ always trip me up, but now I have a clear explanation of why they're needed and how they work.

The key thing I want to remember for next time: mapping files aren't just nice-to-haveโ€”they're absolutely critical for proper ALM. Without them, you're setting yourself up for repository chaos and build headaches down the road.

If future me (or anyone else) is reading this while staring at a broken build or wondering why pac solution sync isn't working, just remember: check your map.xml file, count those parent directory navigations, and make sure your source paths actually exist. Trust me, it's usually one of those three things.

Top comments (0)