.NET Console Application Connection String Transform Error - c#

I'm uploading a console app as a webjob to my app service on azure. I have unloaded the application and told it to include a release config In the csproj:
<Content Include="App.config" />
<Content Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
</Content>
<Content Include="App.Release.config">
<DependentUpon>App.config</DependentUpon>
</Content
along with this at the end:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
<!-- Generate transformed app config in the intermediate directory -->
<TransformXml Source="app.config" Destination="$(IntermediateOutputPath) $(TargetFileName).config" Transform="app.$(Configuration).config" />
<!-- Force build process to use the transformed configuration file from now on. -->
<ItemGroup>
<AppConfigWithTargetPath Remove="app.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
On my local machine the connection string is:
<connectionStrings>
<add name="Default1" connectionString="data source=.\SQLEXPRESS;initial catalog=Default1;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
In the App.Release.Config I have this:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="Default1" connectionString="Server=tcp::NewApplication.database.windows.net,1433;Initial Catalog=NewApplication;Persist Security Info=False;User ID=NewApplicationadmin;Password=testing;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
The console application works fine on my local machine, and the way in which I did my transformations on my web app is exactly the same.
However when I upload it and run it as a webjob it fails giving this error in the log:
Unhandled Exception: System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
What would cause this in this instance?

Related

How to access/read packages in Azure Artifact with PAT token

Is there a way I can connect my Visual studio to Azure Artifact source feed with PAT token? I need to add packages to my project
Solution:
Create a nuget.config file in the root of your project (where sln is). I used the Package Manager Console to run the command "dotnet new nugetconfig"
In the nuget.exe file, I replaced content with following
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="FeedName" value="artifact URL" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json"/>
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
<packageSourceCredentials>
<FeedName>
<add key="Username" value="User" />
<add key="ClearTextPassword" value="%PATTokenEnvrionmentVariable%" />
</FeedNamet>
</packageSourceCredentials>
</configuration>
Then I ran "dotnet restore" and restarted Visual studio

Docker compose build/Docker build connection refused to nuget at macos

I've got a problem with building .NET 5 solutions using docker compose build or docker build.
Image which i'm using for building is:
mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim
The problem is that when I'm trying to build it on my machine (MacOS Monterey, intel) I've got following error with restoring nuget packages from the private feed:
#19 6.349 Failed to download package 'System.Runtime.CompilerServices.Unsafe.4.5.1' from 'https://XXXX.pkgs.visualstudio.com/_packaging/96ca4348-f8c1-4150-b19f-3dab0cf807bf/nuget/v3/flat2/system.runtime.compilerservices.unsafe/4.5.1/system.runtime.compilerservices.unsafe.4.5.1.nupkg'.
#19 6.349 Connection refused (pyvvsblobprodsu6weus63.blob.core.windows.net:443)
#19 6.349 Connection refused
#19 6.357 Failed to download package 'Microsoft.Azure.Storage.Common.11.2.3' from 'https://XXXX.pkgs.visualstudio.com/_packaging/96ca4348-f8c1-4150-b19f-3dab0cf807bf/nuget/v3/flat2/microsoft.azure.storage.common/11.2.3/microsoft.azure.storage.common.11.2.3.nupkg'.
#19 6.357 Connection refused (wg0vsblobprodsu6weus89.blob.core.windows.net:443)
#19 6.357 Connection refused
I'm copying nuget.config with credentials in dockerfile like
COPY nuget.config /
Here is my nuget.config copied to the container:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="NuGet V3" value="https://api.nuget.org/v3/index.json" />
<add key="DDDDD" value="https://XXXX.pkgs.visualstudio.com/_packaging/DDDDD/nuget/v3/index.json" />
</packageSources>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
<config>
<add key="repositoryPath" value="packages" />
</config>
<packageSourceCredentials>
<DDDDD>
<add key="Username" value="SomeUsername" />
<add key="ClearTextPassword" value="SomePassword" />
</DDDDD>
</packageSourceCredentials>
</configuration>
Commands which i'm using to build containers:
docker compose up -d
docker build . -F API/Dockerfile
It's failing for both of them.
Can anybody tell me what's wrong? Maybe it's something with my machine setup?
Self answer for people having the same issue as I had:
The problem was the lack of this line in the nuget config:
in config section like:
<config>
<add key='maxHttpRequestsPerSource' value='10' />
<add key="repositoryPath" value="packages" />
</config>
After adding this key, everything is working as expected.
Keep in mind that your value for maxHttpRequestsPerSource may be different (less or more) so I advise doing a few experiments with other values.

Transform Web.config on build

I have an ASP.NET application with Web.Config configured with several connection strings.
I also have a Web.Debug.config and Web.Release.config which contain transforms for the strings and are applied when deploying. Which works fine.
Example of transform in the Web.Release.config:
<add name ="ConnectionKey" connectionString="Server=*******" providerName="System.Data.EntityClient"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
However I would like the transform to also be applied on builds so I could run a script building my application and running several tests before publishing.
I tried to add the following code in my project's file (Source : https://gist.github.com/EdCharbeneau/9135216 ):
<Target Name="BeforeBuild">
<!-- Transform the file out to a temp file, sourcing from our Web.config file: -->
<TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config.temp"
Condition="Exists('Web.$(Configuration).config')" />
<!-- Copy the temp file, back over the top of Web.config, the file handle opened by TransformXml is closed now: -->
<Copy SourceFiles="Web.config.temp" DestinationFiles="Web.config"
Condition="Exists('Web.config.temp')" />
<!-- Cleanup after ourselves: -->
<Delete Files="Web.config.temp" Condition="Exists('Web.config.temp')" />
</Target>
But when I check the bin folder it's always the default Web.Config that is present, not the transformed one.

web.debug.config does not work

I have a webb aplication where I want to take advantage of the web.debug.config file so that when debugging I use a test database. This does not work for me. I have this in my web.debig.config..
<connectionStrings>
<add name="connStr"
connectionString="Data Source=LocalSqlserverName;Initial Catalog=testdb;Persist Security Info=True;User ID=Myusername;Password=mypassword"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
And in my web.config file this connectionstring point to another database server. But when I debug I can see that the connectionstring in web.config file is used instead of the one in web.debug.config. What am I doing wrong here?
As #esiprogrammer says it normally only transforms on Publish from Visual Studio.
However you can transform Web.config on build. Add this to your *.csproj file:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" />
<Target Name="BeforeBuild">
<TransformXml
Source="Web.Base.config"
Transform="Web.$(Configuration).config"
Destination="Web.config" />
</Target>
Keep the origin configuration in Web.Base.config. It's enough to enable transformation and it works for any XML config file.
Source:
https://stackoverflow.com/a/35561167/3850405

How to add config transformations for a custom config file in Visual Studio?

The project I am working on involves reading a lot of service endpoints (url) from a config file. Since the list would be quite large I decided to keep them in a custom config file to keep my web.config clean and small. I included the custom section to my web as below:
<mySection configSource="myConfig.config" />
I works perfectly fine.
But the problem of transformation appears during the deployment of the project to different environments. I have three web.config files:
Web.config
Web.Uat.config
Web.Release.config
While the transformation web.config works, the transformations for custom config files fails at deployment.
Is there an way I can transform the custom config file during deployment?
Visual Studio transforms only web.config files by default.
If you need custom config file with transformation for DEV, UAT, PROD, etc environments, then try to
Use custom extensions for Visual Studio like SlowCheetah - XML Transforms for Config transformation preview functionality.
Add for the project from Nuget SlowCheetah to provide build in transformation.
A little bit details:
Add VS Extension SlowCheetah from Extensions and Updates
Right click on your myconfig.config and choose add transorm:
Inside each defined configurations insert your own transormation rulles like that:
<services xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<service name="WebApplication1.Services.Service2" xdt:Transform="Replace" xdt:Locator="Match(name)" >
<endpoint address="http://localhost:57939/Services/DebugService" behaviorConfiguration="WebApplication1.Services.Service2AspNetAjaxBehavior"
binding="webHttpBinding" contract="WebApplication1.Services.Service2" />
</service>
</services>
Hope it was helpful
I'm going to extend on Andoni Ripoll Jarauta's answer a little.
We were faced with a similar problem. I wanted to pull the connection strings out of the web.config file to limit merge conflicts. I also wanted create a "release" config containing static information when publishing.
...simple enough. Create a custom config file, webdb.config, and update the web.config file.
Ex.
web.config
<connectionStrings configSource="WebDB.config"/>
wedbdb.config (xml version="1.0" is required for transformation)
<?xml version="1.0" encoding="utf-8"?>
<connectionStrings>
</connectionStrings>
Next add transformation files for webdb.config
WebDB.Debug.config example:
<?xml version="1.0" encoding="utf-8"?>
<connectionStrings xdt:Transform="Replace" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<add name="PRRADDataContainer" connectionString="metadata=~/PRRADData.csdl|~/PRRADData.ssdl|~/PRRADData.msl;provider=System.Data.SqlClient;provider connection string=';Data Source=localhost;Initial Catalog=;User ID=;Password=;multipleactiveresultsets=True;App=EntityFramework';" providerName="System.Data.EntityClient" />
<add name="MyConnectionString" connectionString="Data Source=localhost;Initial Catalog=;Persist Security Info=True;User ID=;Password=;" providerName="System.Data.SqlClient" />
</connectionStrings>
WebDB.Release.config example:
<?xml version="1.0" encoding="utf-8"?>
<connectionStrings xdt:Transform="Replace" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<add name="PRRADDataContainer" connectionString="metadata=~/PRRADData.csdl|~/PRRADData.ssdl|~/PRRADData.msl;provider=System.Data.SqlClient;provider connection string=';Data Source=prod_server;Initial Catalog=;User ID=;Password=;multipleactiveresultsets=True;App=EntityFramework';" providerName="System.Data.EntityClient" />
<add name="MyConnectionString" connectionString="Data Source=prod_server;Initial Catalog=;Persist Security Info=True;User ID=;Password=;" providerName="System.Data.SqlClient" />
</connectionStrings>
Next we need to add an after-build event. This is created by simply editing the CSPROJ file.
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
<TransformXml Source="WebDB.config" Transform="WebDB.$(Configuration).config" Destination="WebDB.config" />
</Target>
Now when I run locally I'll get WebDB.Debug.config and when I publish my code I just need to make sure to select "Release" as the configuration source. In both cases the WebDB.config file will be updated with the corresponding file when you build.
NOTE: make sure you set the webdb.config, webdb.debug.config, and webdb.release.config to "Do not copy" for the "Copy to Output Directory" option.
Hope this helps!
I have been using SlowCheetah but I found something that I think is more elegant. Just telling to the build to generate the .config depending on the build configuration.
Having a app.Release.config in your project (or many more depending on you deployment needs) you just need to edit the project file (the .csproj one if you program in C#). Find the end of it, between the last </ItemGroup> and </Project> and add:
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
<PropertyGroup>
<OutputTypeName>$(OutputType)</OutputTypeName>
<OutputTypeName Condition="'$(OutputTypeName)'=='Library'">dll</OutputTypeName>
<OutputTypeName Condition="'$(OutputTypeName)'=='Module'">dll</OutputTypeName>
<OutputTypeName Condition="'$(OutputTypeName)'=='Winexe'">exe</OutputTypeName>
</PropertyGroup>
<TransformXml Source="Config\app.config" Transform="Config\app.$(Configuration).config" Destination="$(OutputPath)\$(AssemblyName).$(OutputTypeName).config" />
</Target>
</Project>
Save and reload from VisualStudio. Compile in Release mode and check the bin/Release folder on your <MyProject>.config file the transformation is done.
This example applies to Exe and Dll files and any VisualStudio version because includes this post help
There is another approach that doesn't require installing extensions nor using build events.
Let's suppose you have your custom configs like so:
myConfig.config
myConfig.Uat.config
myConfig.Release.config
Then in your main Web.config you have this:
<mySection configSource="myConfig.config" />
Lastly, inside your Web.Uat.config you add a transform like this:
<mySection configSource="myConfig.Uat.config" xdt:Transform="SetAttributes" />
This is not transforming the myConfig.config file, but rather overriding the name of the custom config file that should be used. You can do the same for the Release and any other environments.
Your myConfig.Uat.config should not contain transformations, it should be a copy of the base custom config file, with the appropriate values for the custom environment.
The downside is everytime you add something to the base custom config file, you need to also add to the config files for other envs (even if the value should be the same through envs). So I'd consider just using these custom config files for settings that should be changed between envs.
I had a similar need to transform a custom config file, but in a class library. Andoni Ripoll Jarauta's solution worked when I built the project directly, but when I built another project that referenced it the transformed file would not get copied. I found that in addition I had to add the transformed file to AssignTargetPathsDependsOn for that to happen. This did the trick:
<PropertyGroup>
<AssignTargetPathsDependsOn>
$(AssignTargetPathsDependsOn);
BuildCustomConfig;
</AssignTargetPathsDependsOn>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="BuildCustomConfig">
<TransformXml Source="MyCustom.config" Transform="MyCustom.$(Configuration).config" Destination="$(OutputPath)\MyCustom.config" />
<ItemGroup>
<Content Include="$(OutputPath)\MyCustom.config" Condition="Exists('$(OutputPath)\MyCustom.config')">
<Link>MyCustom.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Target>
Since the OP asked about Web.config transformations during the deployment lets assume the WPP is already in there. So I've hacked on the WPP.
I use the following snippet to transform Umbraco's own config files (but indeed any configs suit well):
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<UmbracoConfigsToTransform Include="Config\umbracoSettings.config">
<DestinationRelativePath>Config\umbracoSettings.config</DestinationRelativePath>
</UmbracoConfigsToTransform>
</ItemGroup>
<PropertyGroup>
<CollectWebConfigsToTransformDependsOn>
$(CollectWebConfigsToTransformDependsOn);
CollectUmbracoConfigsToTransform
</CollectWebConfigsToTransformDependsOn>
</PropertyGroup>
<Target Name="CollectUmbracoConfigsToTransform">
<!-- The logic comes from the 'CollectWebConfigsToTransform' task -->
<ItemGroup>
<WebConfigsToTransform Include="#(UmbracoConfigsToTransform)">
<Exclude>false</Exclude>
<TransformFile>$([System.String]::new($(WebPublishPipelineProjectDirectory)\$([System.IO.Path]::GetDirectoryName($([System.String]::new(%(DestinationRelativePath)))))).TrimEnd('\'))\%(Filename).$(Configuration)%(Extension)</TransformFile>
<TransformOriginalFolder>$(TransformWebConfigIntermediateLocation)\original</TransformOriginalFolder>
<TransformFileFolder>$(TransformWebConfigIntermediateLocation)\assist</TransformFileFolder>
<TransformOutputFile>$(TransformWebConfigIntermediateLocation)\transformed\%(DestinationRelativePath)</TransformOutputFile>
<TransformScope>$([System.IO.Path]::GetFullPath($(WPPAllFilesInSingleFolder)\%(DestinationRelativePath)))</TransformScope>
</WebConfigsToTransform>
</ItemGroup>
</Target>
</Project>
I name it Umbraco.wpp.targets and drop inside project's root. Then the WPP automatically imports it.
All you have then to do is add a transform file (Config\umbracoSettings.Release.config in case of this sample).

Categories