Today I want to talk about something that confuses a lot of developers when working with Dynamics 365 plugins. When should you actually bump your plugin assembly version number? I see this question come up frequently in the community, and I have seen teams struggle with this in real projects.
Some developers increment the version on every single code change. Others never touch it. Both approaches can cause problems. Let me share what I have learned over the years about when you really need to raise that version number.
Understanding Assembly Versioning in D365
First, let me set some context. In .NET, every assembly has a version number with four parts: Major.Minor.Build.Revision (like 1.2.3.4). When you register a plugin assembly in Dynamics 365, the system stores this version number along with your plugin code.
Here is the important part. When D365 loads your plugin, it caches the assembly. If you update your plugin but keep the same version number, you might run into caching issues where the old version keeps executing even after you deploy the new code.
When You SHOULD Raise the Version
Let me be clear about situations where you need to bump that version number.
1. Removing Plugin Types from the Assembly
This is mandatory. If you delete a plugin class from your assembly, you must increment the major or minor version number. D365 tracks which plugin types exist in each version of an assembly. When you remove a plugin without changing the major or minor version, solution imports will fail with an error.
2. Adding New Plugin Classes
Anytime you add a new plugin class that implements IPlugin, increment the version. This ensures D365 recognizes there is new functionality to load.
3. Changing Plugin Logic
If you modify the behavior of existing plugin code, bump the version. Bug fixes, new features, logic changes, all of these count. The behavior is different, so the version should be different.
4. Before Deploying to Higher Environments
This is a best practice I always recommend. Before you deploy to TEST, UAT, or PROD, increment the version. It makes troubleshooting easier because you can clearly see which version is running in each environment.
5. Custom API Changes
If you are working with Custom APIs and you modify the plugin code that implements them, raise the version. Same reasoning applies.
6. Modifying Plugin Dependencies
If you add or update NuGet packages or change assembly references, bump the version. The assembly composition has changed.
When You DON’T Need to Raise the Version
There are situations where changing the version is not necessary and just adds noise.
During Active Development in DEV
If you are actively developing in your DEV environment and making frequent changes, you do not need to bump the version on every save. This keeps your version numbers meaningful.
Code Refactoring Without Behavior Changes
If you are just cleaning up code, renaming variables, or restructuring classes without changing what the plugin actually does, you can skip the version bump during development.
Adding Comments or Documentation
Documentation changes do not need version increments. The functionality is identical.
Performance Optimizations
If you optimize code for performance but the output and behavior remain exactly the same, you can keep the version during development. However, I still recommend bumping it before deploying to higher environments.
A Real-World Scenario
Let me share a real scenario that comes up frequently in the community. A development team was working on a plugin assembly with multiple plugins. They decided to remove one of the plugins because it was no longer needed. They deleted the plugin code from their Visual Studio project, unregistered the plugin and its steps from D365, and updated the assembly.
Everything worked fine in their DEV environment. The solution exported without issues. But when they tried to import the solution as an upgrade to their TEST environment, they hit this error:
Plugin Assemblies import: FAILURE.Error: Plugin: YourAssemblyName, Version=1.0.0.0 caused an exception.Existing plug-in types have been removed. Please update major or minor version of plug-in assembly.
The error message is clear. D365 detected that plugin types were removed from the assembly, but the assembly version stayed the same (1.0.0.0). This is a problem because D365 tracks which plugins exist in each version of an assembly. When you remove a plugin but keep the same version number, it creates an inconsistency.
The solution was simple. They opened the AssemblyInfo.cs file in Visual Studio and changed the version from 1.0.0.0 to 1.1.0.0 (a minor version bump). Then they had to completely unregister the old assembly and register the new version fresh in DEV. After that, the solution upgrade worked perfectly in TEST.
This scenario shows exactly why version numbers matter. They are not just for your reference. D365 uses them to validate that the assembly structure matches what it expects.
Understanding Version Number Changes
According to Microsoft documentation, the way you change your version number affects how D365 handles assembly updates.
Build or Revision Changes (X.X.Build.Revision)
When you only change the build or revision number (the last two digits), D365 treats this as an in-place upgrade. The old version is automatically removed when you import the solution. Any existing plugin steps automatically point to the new version. This is the smoothest upgrade path.
Major or Minor Changes (Major.Minor.X.X)
When you change the major or minor version number (the first two digits), D365 treats this as a completely different assembly. The old assembly and the new assembly can coexist. Existing plugin steps will continue pointing to the old assembly version. You need to manually update step registrations if you want them to use the new assembly version.
This is why removing plugin types requires a major or minor version change. D365 needs to know this is a fundamentally different assembly, not just an update to the existing one.
Best Practices for Version Management
Here are some practices that work well for plugin projects.
Use Semantic Versioning
Follow a meaningful versioning pattern:
- Major version for breaking changes or major features
- Minor version for new functionality
- Build number for bug fixes
- Revision can be auto-generated or left at 0
Configure Your AssemblyInfo.cs
Here is how I typically set up the AssemblyInfo.cs file:
using System.Reflection;using System.Runtime.InteropServices;[assembly: AssemblyTitle("CrmMindsPlugins")][assembly: AssemblyDescription("Dynamics 365 Custom Plugins")][assembly: AssemblyConfiguration("")][assembly: AssemblyCompany("CrmMinds")][assembly: AssemblyProduct("CrmMindsPlugins")][assembly: AssemblyCopyright("Copyright © 2026")][assembly: AssemblyTrademark("")][assembly: AssemblyCulture("")][assembly: ComVisible(false)][assembly: Guid("12345678-1234-1234-1234-123456789abc")]// Version format: Major.Minor.Build.Revision// Increment Minor for new features// Increment Build for bug fixes[assembly: AssemblyVersion("1.2.0.0")][assembly: AssemblyFileVersion("1.2.0.0")]
Automate Version Updates in CI/CD
If you are using Azure DevOps or another CI/CD pipeline, you can automatically increment the version. Here is a PowerShell snippet that updates the AssemblyInfo.cs file:
# Set the new version$majorVersion = 1$minorVersion = 2$buildNumber = $env:BUILD_BUILDNUMBER # From CI/CD pipeline$newVersion = "$majorVersion.$minorVersion.$buildNumber.0"# Path to AssemblyInfo.cs$assemblyInfoPath = ".\CrmMindsPlugins\Properties\AssemblyInfo.cs"# Read the file$content = Get-Content $assemblyInfoPath# Update version lines$content = $content -replace 'AssemblyVersion\(".*?"\)', "AssemblyVersion(`"$newVersion`")"$content = $content -replace 'AssemblyFileVersion\(".*?"\)', "AssemblyFileVersion(`"$newVersion`")"# Write back to file$content | Set-Content $assemblyInfoPathWrite-Host "Updated assembly version to $newVersion"
This ensures every build gets a unique version number automatically.
Verify the Version in D365
After deploying, always verify which version is running. You can check this in the Plugin Registration Tool or by querying the PluginAssembly table:
// FetchXML to get plugin assembly versionsvar fetchXml = @"<fetch> <entity name='pluginassembly'> <attribute name='name' /> <attribute name='version' /> <attribute name='modifiedon' /> <filter> <condition attribute='name' operator='eq' value='CrmMindsPlugins' /> </filter> </entity></fetch>";
You can run this in XrmToolBox or in your own diagnostic tool.
The Exception: When Version Doesn’t Matter
There is one situation where the version number becomes irrelevant. If you completely unregister the plugin assembly and then register it fresh, D365 loads whatever version you provide. The cache is cleared because the registration is new.
However, this approach is not practical for production environments. You would have to delete all plugin steps, remove the assembly, and recreate everything. That causes downtime and is risky.
My Recommendation
If you are not sure whether to bump the version, just bump it. The cost of incrementing a number is zero. The cost of debugging mysterious caching issues can be hours or even days.
Here is my personal rule: Any time code leaves my development machine and goes to another environment, the version gets incremented. Any time functionality changes in a way that users or other systems might notice, the version gets incremented.
Be consistent within your team. Document your versioning policy and make sure everyone follows it. This is especially important in larger teams where multiple developers work on the same plugin project.
Wrapping Up
Plugin assembly versioning in Dynamics 365 is more important than it might seem at first. The version number is not just documentation. It is a signal to D365 about when to reload your code. Get it wrong, and you can spend hours chasing phantom bugs caused by cached assemblies.
My advice is simple. Bump the version whenever you deploy to a shared environment or make functional changes. Automate it in your build pipeline if possible. Verify what version is running after deployment. These small habits will save you significant troubleshooting time.
Now go check your plugin projects and make sure you have a clear versioning strategy. Your future self will thank you.
Until next time, happy coding!
Leave a comment