ProConcepts 2.0 Migration Guide - Esri/arcgis-pro-sdk GitHub Wiki

ArcGISPro 2.0 was a breaking change release. The 2.0 API changes and the procedure for migrating your 1.x add-ins and configurations are discussed within this document.

Language:      C#
Subject:       Framework
Contributor:   ArcGIS Pro SDK Team <[email protected]>
Organization:  Esri, http://www.esri.com
Date:          9/28/2021  
ArcGIS Pro:    2.9 
Visual Studio: 2017, 2019

In this topic

Overview

ArcGIS Pro 2.0 .NET assemblies are strong named at 2.0. This was a breaking change. It requires a recompile of your 1.x add-ins and configurations. When you do recompile your add-ins and configurations you may get compilation errors caused by changes to the ArcGIS Pro 2.0 APIs which you will have to fix. This document discusses the breaking changes and migration procedure for add-in and configuration developers.

For the purposes of this document only add-ins are mentioned to avoid repetitive mentions of "add-ins and/or configurations" in the text. However, all information and instructions apply equally to both.

Breaking Changes

At 2.0, breaking changes can be organized into the following categories:

  • Strong naming
  • Factory class changes
  • Synchronous methods
  • Deprecated types and members
  • Other API changes

Your 1.x add-ins and configurations must be recompiled at 2.x. Step by step instructions on the migration procedure can be found in the migration procedure section. A variety of "before" and "after" migration snippets are available in ProSnippets Migrating to 2.0.

Strong Naming

Historically, strong naming was the mechanism associated with COM and the GAC. However, strong naming is also used to uniquely identify individual versions of a specific assembly. To support those 3rd parties who need to deploy multiple versions of their own proprietary assemblies (that reference Pro APIs) with their add-ins, Pro now strong names its assemblies.

Changing the Pro assemblies from weak named ("non" strong named) to strong named is a breaking change. You must recompile your add-in or it will not load at run time. Recompilation is necessary whether you intend to strong name your add-in or not and whether you have API changes to correct or not.

Note:

  • You do not need to change your project references within visual studio.
  • You may incur compiler errors because of API changes when you recompile (consult the various API changes below).
  • You do not need to strong name your add-in assembly to use the Pro strong named assemblies. A weak-named add-in assembly will work with strong named assemblies the same as a strong named one.

Factory Class Changes

Prior to 2.0, factory methods were static (i.e. accessed directly off the class). At 2.0, the methods became instance methods that are accessed off a factory singleton Instance property. The following factory classes have been changed to singletons:

Namespace 1.4 and prior 2.0
ArcGIS.Desktop.Core ItemFactory ItemFactory.Instance
ArcGIS.Desktop.Mapping ColorFactory ColorFactory.Instance
ArcGIS.Desktop.Mapping LayerFactory LayerFactory.Instance
ArcGIS.Desktop.Mapping MapFactory MapFactory.Instance
ArcGIS.Desktop.Mapping StandaloneTableFactory StandaloneTableFactory.Instance
ArcGIS.Desktop.Mapping SymbolFactory SymbolFactory.Instance

For example (using SymbolFactory and ColorFactory):

1.4 or earlier:

 //Create a polygon symbol
 var outline = SymbolFactory.ConstructStroke(ColorFactory.BlueRGB, 2.0, SimpleLineStyle.Solid);
 var fillWithOutline = SymbolFactory.ConstructPolygonSymbol(ColorFactory.RedRGB, SimpleFillStyle.Solid, outline);

2.0 or later:

 //Create a polygon symbol
 var outline = SymbolFactory.Instance.ConstructStroke(
                         ColorFactory.Instance.BlueRGB, 2.0, SimpleLineStyle.Solid);
 var fillWithOutline = SymbolFactory.Instance.ConstructPolygonSymbol(
                         ColorFactory.Instance.RedRGB, SimpleFillStyle.Solid, outline);

Note the changes in the "2.0" example to usage of Factory.Instance.Methods. Although not a factory class, the ArcGIS.Core.Geometry.GeometryEngine has also been changed to use a GeometryEngine.Instance member.

Synchronous Methods

At 2.0, a number previously asynchronous methods became synchronous. Synchronous methods lend themselves to being integrated into sequential workflow steps whereas asynchronous methods do not. Typically, steps within an add-in workflow are executed sequentially while the entire workflow, or coarse-grained aspects of the workflow, is executed asynchronously.

The syntax for executing asynchronous methods sequentially in-conjunction with synchronous methods (usually via async and await semantics) can be difficult. Asynchronous methods work best when they are coarse-grained and are to be executed singly from the UI thread and not from within a QueuedTask.Run lambda. Consult the migration procedure section in this document for guidance on how to migrate your code as well as ProSnippets Migrating to 2.0 for examples.

Developers needing coarse-grained asynchronous equivalents of individual Pro synchronous methods should wrap the synchronous method in a QueuedTask.Run lambda to make their own custom, asynchronous API method. Here is an example of a custom asynchronous equivalent of MapFactory's synchronous CreateMap method:

 using ArcGIS.Core.CIM;
 using ArcGIS.Desktop.Mapping;
 
 //Provide an asynchronous flavor of CreateMap
 public Task<Map> CreateMapAsync(string name, MapType mapType,
            MapViewingMode defaultViewingMode, Basemap basemap) {
   return QueuedTask.Run(() => 
             MapFactory.Instance.CreateMap(name, mapType, defaultViewingMode, basemap));
 }

 //Or...as an extension method
 public static MapFactoryExtensionMethods {

   //Provide an asynchronous flavor of CreateMap as an extension method
   public static Task<Map> CreateMapAsync(this IMapFactory factory, string name, MapType mapType,
            MapViewingMode defaultViewingMode, Basemap basemap) {
   return QueuedTask.Run(() => 
             factory.CreateMap(name, mapType, defaultViewingMode, basemap));
 }

Deprecated Types and Members

Deprecated types and members were deleted at 2.0. Use of a deprecated type or member will have shown up as a compiler warning previously in Visual Studio. Code that referenced a deprecated type or member must be changed to use its replacement. All types and members previously marked as [Obsolete] have been deleted.

Other API Changes

At 2.0, there were a number of other API changes that did not fall into the above categories. These are changes to type names, members, and or method parameters. A complete listing of all API changes can be found in the What's New for Developer's at 2.0.

Changes

At 2.0 changes were made in the following areas. These should not be considered 'breaking' as they do not require recompilation of your add-ins. However, it is still recommended you alter your add-ins as needed to accommodate these changes.

Config.daml desktopVersion

ArcGIS Pro add-ins are forwards compatible across minor releases only. They are not forwards compatible across major releases. The switch from 1.4 to 2.0 is a major release. Add-ins created prior to 2.0 will have a desktopVersion value in their config.daml file of "1.4" or less which must be changed manually to "2.0" or later or the add-in will not load. Pre-Migration and the migration procedure provides more details. The add-in versioning scheme is explained in detail in the ProConcepts Advanced Topics.

ArcGIS Pro WPF Styles, Brushes, and Colors

The ArcGIS Pro WPF styles, brushes, and colors for use by third parties have been renamed to make the their names more consistent as well as give a better indication of their usage. For example, there is now a brush named "Esri_TextSelectionHighlightBrush" which replaces the previously named "Esri_Blue" brush. The new name more clearly indicates its use as a text selection highlighting brush (e.g. for use when text is selected in a text block) than its old name "Esri_Blue" which only gives an indication of its color ("blue"), not of its use (as a text highlight).

The previous WPF styles, brushes, and colors are still present but should be considered internal and are not supported. 3rd parties wanting to use ArcGIS Pro WPF resources in their user control add-in content should only use the resources documented in the ProGuide Style Guide. You should change all WPF UI code currently using Pro 1.x resources to use the new set of resources available at 2.x. Internal Pro styles, brushes, and colors are subject to change without notice.

Tab Captions

Tab captions on the Pro Ribbon are now Title Case and not ALL CAPS. At 2.0 or later, consider title casing any custom TAB captions in your respective add-in config.daml files.

1.x, ALL CAPS:

ProRibbonOld2.png

2.0, Title Case:

ProRibbon.png

Pro Document Version Change

At ArcGIS Pro 2.0, the document version of ArcGIS Pro Projects and project templates (.aprx, .ppkx, and .aptx) was likewise changed to 2.0. Any project created or saved using ArcGIS Pro 2.0 will be saved with a document version of 2.0. Projects and project templates with a document version of 2.0 can only be opened by ArcGIS Pro 2.0 or later. Conversely, Projects created with a document version of 1.x can be opened both by ArcGIS Pro 1.x and 2.0.

Any project saved by ArcGIS Pro 2.0 will have its document version changed to 2.0. If the project was originally created with ArcGIS Pro 1.x, a warning will appear before changes are saved. If you proceed, the document version of the project will be changed to 2.0, and ArcGIS Pro 1.x will not be able to open it. If the project is shared with others, consider saving a copy of the project that is specific to ArcGIS Pro 2.0 using Save As. Consult https://pro.arcgis.com/en/pro-app/help/projects/save-a-project.htm for more information.

Pre-Migration

Add-in and Configuration Registration

Until you have migrated your add-ins and configurations, attempts to register your .esriAddinX and .proConfigX on a ArcGIS Pro 2.0 machine will fail. RegisterAddin.exe will pop-up a warning message alerting you that the add-in or configuration you are attempting to install won't be loaded because it is incompatible with the current version of Pro.

IncompatibleAddin.png

Proceeding with the installation will still deploy the archive file to the respective folder but when Pro starts it will not be loaded.

Add-in and Configuration Does Not Load

In many cases you may already have add-ins or configurations installed on your machine when you upgrade Pro and you do not (or did not) run RegisterAddin.exe. When you run Pro you notice that your custom tab or buttons are missing from the Pro UI. The probable cause is that the add-ins or configuration have not been migrated from 1.x and were skipped in the loading sequence. To confirm this (especially if you are not the owner of the source code) you can:

Either:

  • Run ArcGISPro.exe with the /enablediagnostics command line argument to enable event logging (you may need to use a desktop shortcut to add the command line argument. A full list of ArcGISPro command line arguments can be found here ProGuide Command lines switches for ArcGISPro.exe. Check the log after Pro has started for warnings related to add-ins or configurations not loaded because of version incompatibility.
<?xml version="1.0"?>
<EventLog ver="1">
 ...
 <Event time="Tue May  2 14:13:20 2017" type="Info">Processing add-in: C:\Users\...\Documents\ArcGIS\AddIns\ArcGISPro\{23b8e6aa-...}\ProAppModule1.esriAddinX</Event>  <--this one loaded ok

  <Event time="Tue May  2 14:13:20 2017" type="Warn">Invalid add-in desktopVersion number: 1.3.5563</Event><-- problem!
  <Event time="Tue May  2 14:13:20 2017" type="Info">Processing add-in: C:\Users\...\Documents\ArcGIS\AddIns\ArcGISPro\{3b62f119-...}\CIMViewer.esriAddinX</Event><-- this Add-in did not load.

  <Event time="Tue May  2 14:13:20 2017" type="Info">Processing add-in: 

Or:

  • Go to the Add-in manager on backstage. Incompatible add-ins that have not been migrated will be shown as disabled. Their status will be listed on the add-in manager tab. For example, here the add-in "CIMViewer.esriAddinX" has not been migrated from version 1.3 and so it did not load.

Add-inManager.png

Migration Procedure

To migrate your 1.x add-ins and configurations to 2.x, please use the following procedure:

Step 1

In Visual Studio, open your add-in or configuration config.daml. Change the desktopVersion attribute of the AddInInfo element to 2.0.

<!-- Before -->
<?xml version="1.0" encoding="utf-8"?>
<ArcGIS defaultAssembly="...dll" defaultNamespace="..." xmlns="..." xmlns:xsi=...>
  <AddInInfo id="{fa4234de-...}" version="1.0" desktopVersion="1.4.7198">
    <Name>...
  

<!-- After -->
<?xml version="1.0" encoding="utf-8"?>
<ArcGIS defaultAssembly="...dll" defaultNamespace="..." xmlns="..." xmlns:xsi=...>
  <AddInInfo id="{fa4234de-...}" version="1.0" desktopVersion="2.0">
    <Name>...

Step 2

Build your add-in or configuration. Note: You do NOT have to change your assembly references to switch to Pro's strong named assemblies. Rebuilding with Pro 2.0 installed will automatically switch the references for you.

Step 3

Fix any compilation errors from Step 2. Errors will likely fall into the following categories:

  • Code that uses the static factory classes is broken. At 2.0, the factories and GeometryEngine have been changed to Singletons. The singleton instance property is called "Instance". For example:
 //old
 var symbol = SymbolFactory.ConstructPointSymbol(
                    ColorFactory.RedRGB, 8, SimpleMarkerStyle.Circle);

 //new - note the use of the property "Instance"
 var symbol = SymbolFactory.Instance.ConstructPointSymbol(
                    ColorFactory.Instance.RedRGB, 8, SimpleMarkerStyle.Circle);
 //old
 var polyline = PolylineBuilder.CreatePolyline(circularArc);
 var lineBuffer = GeometryEngine.Buffer(polyline, 10);

 //new
 var polyline = PolylineBuilder.CreatePolyline(circularArc);
 var lineBuffer = GeometryEngine.Instance.Buffer(polyline, 10);
  • Code that used an 'Async" method is broken. The "Async" method has been replaced with a synchronous equivalent. For those methods where the asynchronous method has been replaced with a synchronous method the general procedure to change your code will be:

    • Call the synchronous method within the lambda of a QueuedTask.Run (if not already part of a QueuedTask lambda)
    • Delete any await keyword in front of the (original async) method call.
      • This may require you to remove the async keyword from the parent method declaration
    • Change the return type of your containing method if needed
      • It may be that your containing method will no longer return Task or a typeof Task.
      • Consider deleting any Async suffix from your methods if they become synchronous.

For example:

 //old - get a folder connection, enumerate its contents
 var folderConnection = Project.Current.GetItems<FolderConnectionProjectItem>()
       .FirstOrDefault(folder => folder.Name.Equals("PlantSpecies"));
 IEnumerable<Item> folderContents = await folderConnection.GetItemsAsync();
 ...

 //new - note use of synchronous "GetItems". A QueuedTask.Run has been added. 
 //The "await" has been removed
 await QueuedTask.Run(() => {
   var folderConnection = Project.Current.GetItems<FolderConnectionProjectItem>()
            .FirstOrDefault((folder => folder.Name.Equals("PlantSpecies")));
   IEnumerable<Item> folderContents = folderConnection.GetItems();
   ...
 });

Here is another (somewhat contrived) example to illustrate converting a previously asynchronous custom method to a synchronous method:

1.4 or earlier:

 //old
 //Custom asynchronous method. Returns type of Task
 public Task<IList<SymbolStyleItem>> GetPointSymbolsFromStyleAsync(
         StyleProjectItem style, string searchString) {
    if (style == null)
       throw new System.ArgumentNullException();

    //Search for point symbols
    return style.SearchSymbolsAsync(StyleItemType.PointSymbol, searchString);
 }

 //old
 //usage - somewhere else in the add-in - note use of the async method within a QTR
 await QueuedTask.Run(async () => {
   //workflow code here
   ...
   var pointSymbols = await GetPointSymbolsFromStyleAsync(...

At 2.0 or later

 //new
 //1. Custom method changed to be synchronous (no Task return type). 
 //2. Async suffix deleted (convention only, not required).
 //3. GetPointSymbolsFromStyle must be called within a QueuedTask.
 public IList<SymbolStyleItem> GetPointSymbolsFromStyle(
           StyleProjectItem style, string searchString) {
     if (style == null)
         throw new System.ArgumentNullException();

     //Search for point symbols. Will throw CalledOnWrongThread exception 
     //if called from the UI
     return style.SearchSymbols(StyleItemType.PointSymbol, searchString);
 }

 //new
 //usage - somewhere else in the add-in. Workflow still executed asynchronously
 //1. await in-front of GetPointSymbolsFromStyle deleted
 //2. `async` deleted from the QueuedTask.Run lambda
 await QueuedTask.Run(() => {
   //workflow code here
   ...
   var pointSymbols = GetPointSymbolsFromStyle(...

Please consult {ProSnippets Migrating to 2.0 for more migration examples.

  • Code that used a type or member marked as deprecated must now switch to the replacement. All types and members previously marked as [Obsolete] have been deleted.

  • Code is using a type or member that has been changed at 2.0. Consult the What's New for Developer's at 2.0 for a complete list of the API changes.



Additionally:
  • User controls that use Pro styling should change their use of Pro styles, brushes, and colors to the new styles, brushes, and colors released with 2.0. A complete list of the new Pro styles for the API can be found here: ProGuide Style Guide. The previous Pro WPF styles, brushes, and colors you may have been using at 1.4 and earlier are no longer supported.

  • The case of tab captions has changed from UPPER CASE to Title Case. Consider changing the case of your tab captions in your config.daml file to title case to match the tab captions of Pro.

  • If your add-in project is implemented within Visual Studio 2013, consider converting it to Visual Studio 2015 or 2017. At 2.0, Visual Studio 2013 was no longer supported. To convert the your project simply open it within the either version 2015 or 2017 of visual studio. Conversion will be handled automatically.

Step 4

Re-run ArcGIS Pro. Check that your add-in (or configuration) loads correctly.

⚠️ **GitHub.com Fallback** ⚠️