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
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.
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.
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.
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.
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 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.
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.
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.
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.
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 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:
2.0, Title Case:
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.
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.
Proceeding with the installation will still deploy the archive file to the respective folder but when Pro starts it will not be loaded.
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.
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 (originalasync
) method call.- This may require you to remove the
async
keyword from the parent method declaration
- This may require you to remove the
- Change the return type of your containing method if needed
- It may be that your containing method will no longer return
Task
or a typeofTask
. - Consider deleting any
Async
suffix from your methods if they become synchronous.
- It may be that your containing method will no longer return
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.