Overcoming namespace clashes when upgrading to Bot Framework 4.3

V4.3 comes with some nice additional support that I was eager to use. However, there is a problem. v4.3 (Microsoft.Bot.Builder.Azure) uses the latest variant of the Azure Storage library whereas Microsoft.AspNetCore.All, via Microsoft.AspNetCore.DataProtection.AzureStorage (2.2.0), uses the older variant. This can cause problems if your own code wishes to use one of the clashing types. E.g. if you add


CloudStorageAccount blah = new CloudStorageAccount(null, false);

Then you’ll get an error like The type X exists in both Y and Z, e.g.


error CS0433: The type 'CloudStorageAccount' exists in both 'Microsoft.Azure.Storage.Common, Version=9.4.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' and 'Microsoft.WindowsAzure.Storage, Version=9.3.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

The only solution I’ve found is to utilize the obscure extern and some trickery I grabbed from SO – using extern alias.

Step 1 – Create (or ensure there is) an xml file in the root of your project called Directory.Build.targets (don’t put .xml as the extension)

Step 2 – populate with;

  
<Project>
  <Target Name="AddPackageAliases" BeforeTargets="ResolveReferences" Outputs="%(PackageReference.Identity)">
    <PropertyGroup>
      <AliasPackageReference>@(PackageReference->'%(Identity)')</AliasPackageReference>
      <AliasName>@(PackageReference->'%(Alias)')</AliasName>
    </PropertyGroup>

    <ItemGroup>
      <ReferencePath Condition="'%(FileName)'=='$(AliasPackageReference)'">
        <Aliases>$(AliasName)</Aliases>
      </ReferencePath>
    </ItemGroup>
  </Target>
</Project>
  

Step 3 – edit the project. Unload your bot project, edit it and find the reference you wish to alias. Add Alias= E.g. to add the alias AzureCommon

<ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.9.1" />
    <PackageReference Include="Microsoft.ApplicationInsights.TraceListener" Version="2.9.1" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.All" />
    <PackageReference Include="Microsoft.Azure.KeyVault.Core" Version="3.0.3" />
    <PackageReference Include="Microsoft.Azure.Storage.Common" Version="9.4.2" Alias="AzureCommon"/>

Save and reload the project

Step 4 (optional) -That should be enough to provide the separation for the compiler. But if you want to use the aliased version then add the extern to where you wish to use the clashing type, e.g.;


extern alias AzureCommon;
using AzureStore = AzureCommon;

...

AzureCommon.Microsoft.WindowsAzure.Storage.CloudStorageAccount blah =
new AzureCommon.Microsoft.WindowsAzure.Storage.CloudStorageAccount(null, false);

Step 5 – celebrate you’ve avoided this hiccup 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s