Solutions are the foundation to good Power Platform development, without them we have no proper alm and no good way for admins to view flows and apps. But what exactly is a solution and how does it work.
Solutions are often described as boxes, containing all the components of a app/flow/bot/site, but that's not quite accurate, it's actually just a list. I describe it as a more like a fantasy football team (trust me), and that's because each item in a component can be in multiple solutions, like a player can be in multiple fantasy football teams (see kinda makes sense doesn't it 😎). The key thing here is if the component gets edited in one it gets edited in all (So if player scores or gets injured it impacts all teams).
There are also 2 states of a solution, cloud and artifact, the Cloud is simply a collection of related Dataverse Tables and the Artifact a zipped file containing XML, JSON, and some media files.
For this blog Im going to look at the following
- Default Solution
- Managed and Unmanaged
- Solution Layers
- Visibility
- Depenedencies
- Sharing Components
- Cloud Tables
- Artifact Files
Default Solution
This is the underlying solution for all environments and can not be exported. It contains all of the system soluitions (like Approvals) and is also the default location for all solution components. That means that every component you create is also in the default solution (the eagle eyed may have seen a solution id in all of the tables, and this is the reason we cant use it very often, as it normally points to the default environment).
This is also why if we delete an unmanaged solution the components are not deleted, as they are still in the default solution. All we are doing is removing them from the solution, so next time remember to delete all of the solutions contents before deleting it.
Though this is not the case if is managed, if you delete the managed solution the components are deleted from the Default too.
The Common Data Service Default Solution is similar but is where components are stored if you don't create in your own solution. They will appear in both Default and Common Data Service Default Solution
The Common Data Service Default Solution appears in the flows Solution section like personal solutions, but the default will never appear.
Managed and Unmanaged
The next thing to talk about is managed, managed solutions should be read only, but that is not true. What it means is the components cant be edited, but you can still make changes by adding customization/solution layers, these layers can play havoc on alm and really cause more negatives then positives (so I do not use them), see solution layers for more info. To stop customization/solution layers you have to update each component 'Managed Properties'.
Though a couple of callouts here, this property does not seem to impact Connection References, Environment Variables or Apps (as they can not be edited in the solution no matter what the setting). The good news is for environment variables and connection references this is limited to the solution, so go to the default solution and you can still edit them 🤷♂️
Solution Layers
Also known as customization layers, think of these as kind of versions of your solution. They record changes between the base managed layer and will always run as a priority.
This means that if you have a solution a layer in production and import a new updated managed solution the solution layer will still be the live version (nightmare I know).
If you have alm (Dev/Test/Prod) this is normally not an issue unless you use flows etc across solutions e.g
Solution 1 managed with flow 1_v1
Solution 2 managded with flow 1_v2
The flow 1_v2 changes will appear as a solution layer in Solution 1 as it cannot be edited.
I generally recommend against them, some people use them for hot fixes in production (as it allows you to make a quick edit and then roll back when full fix) but I never like editing in prod.
Visibility
As the solution does not have a owner it is open for everyone, that means anyone can see it and add to it. What makes that painful is you cant see what others have added (unless they share with you). This can lead to dependency issues, as when you export you can only export what you cant see (this could be a good practical joke if you wanted to 😎 ).
Additionally unlike non solution aware flows admins can see all of the components of a solution, this is so much easier then having to go to the admin center and sharing one by one.
Dependencies
Depenedencies are created when you reference a component not in the solution. This can be ok if the target environment already has the components, else this will cause the import to fail.
There are 2 ways to see dependencies (kind of from both ends)
To see if any other solutions have dependency on this solution (so it's in this solution and referenced in another solution) you can select 'Show Dependencies' from the solution.
This allows you to see if you edit/try to delete a component the impact it will have outside of the solution.
To see if you have any missing dependencies you have to run the Solution checker.
One of the most common reasons I found is if the missing components are not shared with you or if it is an unused connection reference.
Sharing Components
One of the best things about solutions is the components ensure everything is in a Dataverse table so is a lot easier to share.
With Flows you can change the flow owner (outside of solution you can only share).
Additionally Connection References and environment variables can be shared (to help with the visibility issue). This unfortunately cant be done in the solution, but if you go to the advanced settings from make.powerApp.com you can find the entry in the relevant table and share (note Environment variables you have to share from both the definition and value table)
If you want to know more about advanced settings check out this previous blog Change Solution Owners. It's about changing owner not sharing but the process is practically the same.
Cloud Tables
Solution
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/solution
The first table is the 'solution' table (no surprises there), each solution is just a row in this table, it holds the solution specific information like name, display name, id, version and type.
A thing to consider is, although the solution has a created by, this value is not really used. It isn't available to filter in the solution viewer, instead you should be using the 'Publisher'. So you should be setting this to you or your team so that you can easily filter the solution explorer.
Solution Components
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/solutioncomponent
The SolutionComponents table is the link between the solution and its contents. See as the flow etc (aka component) can be in multiple solutions, we cant create a direct relationship with a solution guid in the component. So the SolutionComponents lists every component and a solution. So a flow in solutions would be in the solutions table twice (well actually 3 times due to the default environment but we will come to that later).
The very strange thing about this table is you cant see it in the Tables section or even the advanced settings, but you can with the Dataverse API (e.g. flow connectors)
The SolutionComponents will have the guid for the component from its host table, a component guid, the solution guid, type of component and more.
Component Code | Componet Description |
---|---|
29 | Process (flows) |
300 | Canvs Apps |
380 | Environment Variable Def |
381 | Environment Variable Value |
x10039 | Connection References |
372 | Connector |
Update
So its turns out not all Connection References are code 10039. Component codes link directly to a table (almost like a GUID), and they are added sequentially. Custom tables start at 10000, and as connection references are a installed solution, they are classified as custom tables. So the number depends on the sequence it was installed, and can be different.
The work around is to use the entities table, which you can query and then return the Component:
objecttypecode eq componentCode
Table name (Component Descreption) returned to be used
entitysetname
Component Tables
The final tables are the tables of the contents/components, so if you add a flow(s) you add those rows from the flows table aka process or workflows.
A couple more kind of key tables are:
Connection References
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/connection
In the ConnectionReference table it lists all the references, with the name, id and type (the actual connection tokens are not stored in here).
Environment Variables
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/environmentvariabledefinition
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/environmentvariablevalue
Now theses are a little funky (and I have no idea why Microsoft decided to do it this way), and that's because there are 2 tables, a definition and value. The definition table is the display name of the environment variable, and the value the value. To create a relationship we use the Schema Name (in the definition table but in the value table Environment Variable Definition).
The basic relationships look like this, with additional tables for PVA, custom connectors, Dataverse choices, Security Roles, etc
- Flows - https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/workflow
- Canvas Apps - https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/canvasapp
- Custom Connectors - https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/entities/connector
Artifact Files
The solution artifact is a zip file then has 3 base files and then dependent on the contents
Customizations.xml
Think of this as the contents page for your solution, it lists all the components, including flows, apps, connection references, variables, Tables etc. IE its the solutionComponent records for the solution.
Each Component type is grouped together and includes the fields/keys from the solutionComponents table e.g
- ID
- Category (For flows Cloud/Desktop/Business)
- IsCustomizable
- StateCode
- DisplayName
And for Tables each of the fields/keys are included.
Quick call out, though other components are referenced here but held in other files, connection references are referenced and held, so they are not in any other file within the solution.
Solution.xml
This is all the key information for the solution (the data from the solution table record). Key information includes:
- UniqueName
- Display Name
- Version
- Managed/unmanaged
- Publisher
FYI you can edit this file and change a managed to unmanaged simply by updating the right node
0= unmanaged
1= managed
It also includes a list of any missing dependencies:
[Content_Types].xml
This one appears to be list of what file types you have (nothing really useful for us).
The below example shows XML (see above), JSON (for flows) and msapp (Canvas App)
Additionally the solution will contain your components, at a top level:
Environment Variables - each has own folder and contains a XML file for the definition record and a JSON file for the value record
Flows - Each has a definition JSON file
Canvas Aps - Use a file time msap, which are just zip files (so if you rename to .zip you will see the contents)
As you can add many more things to a solution I won't go into more detail, I started mapping out a few of the most common in a live whimsical board if you want to take a look.
https://whimsical.com/solution-contents-2q6UkDUPHTubYizqKoq7Sf
As you can see there are a lot to solutions, and although as developers and admins we may not think we need to know, I have found this knowledge so useful when dealing with unexpected bugs.
Top comments (4)
Wow!!! The guide nobody must miss. Really great. Saved it to my bookmarks as having it in my pocket.
Thanks for sharing this knowledge!!! You are the guy ;)
great article, applied the managed to unmanaged switch before as a workaround, so far no bad surprises
Great content. Though - I believe there is more nuance to changing a managed solution to unmanaged than simply flipping the bit. - Would love to hear others experience with attempting to do this.
I suspect you are right, there are so many different moving parts. But in my experience so far it has always worked so worth a try.