.Net Core 3.0 NuGet DLLs - .net-core

Let's say that we include Nuget Package Microsoft.Extensions.Configuration in a Console .Net Core app, and include the same package in another Console .Net Core app.
When we publish these two apps, each app would publish:
Microsoft.Extensions.Configuration.Abstractions.dll
Microsoft.Extensions.Configuration.dll
in each folder.
If we had 10 console apps using the same package, we would have these dlls in 10 different folders in the application server. If we reference to multiple NuGet packages, the number of dependency dll files would multiply.
Is there a way to consolidate these dlls in one folder in the app server, so when we publish our executable, all we need to do is move the executable and configuration file to the server, and it will find these dlls in a common folder. Sort of setting a dll Path.

In consideration of Trisped's suggestion, I am posting an answer that neither me nor my boss are completely satisfied with. But for the time being to the best of my knowledge, the way to consolidate these DLLs is by writing a utility program to move those DLLs to a designated common DLL folder. And, at the same time update both .deps.json file and .runtimeconfig.json file with the new location path of the common DLL folder and additionalProbingPaths folder path structure, respectively.
We can't do this by hand manually because there would be too many DLLs to move and too tedious to edit .deps.json file, which got wiped out everytime we publish the Console App solution. I have written the utility program. Unfortunately this is company's IP so I can't share the code.
The idea is to enumerate the DLLs in the publish folder and store those filenames in a collection / dictionary, and later on use that dictionary to update the runtime dll paths in .deps.json. For CLI use, I use these options:
-c Release -f netcoreapp3.0 --self-contained false -r --runtime win-x64 -o <publisheFolder>
It would be very helpful if Visual Studio Publish Profile would include a folder that we can specify, where all Third Party and Nuget Package DLLs will reside, in addition to the Publish folder, where only the app executable, app dll, configuration files, deps.json and runtimeconfig.json will reside. Even better if the CLI would allow additional option to specify the DLL folder and, not include the runtime folder when --self-contained false is indicated.
After all, isn't one of the main purpose of DLL to allow applications to share code with each other?

Related

ASP.NET Website CI using Azure Dev Ops Pipeline

I've a legacy project, which is a ASP.net Website project(not having .csproj file). It holding .aspx files and packages.config for nuget and other dependencies. Now I want to deploy it to Azure app service by automation with CI/CD in Azure Dev Ops pipeline.
I can't find anything which is suitable for all tasks I need for CI.
Here I don't have .csproj, so I build it using packages.config
Task I tried
Update .sln to .config, because I have more than one website in single solution.
Update Nuget Restore task with install, it doesn't work with restore
And while queue, this pipeline got failed on Build task
Error it thrown
Visual Studio Build task cannot build packages.config file, this task uses MSBuild to build. In Solution argument, only .sln file or .*proj file can be specified.
Solution: Required) If you want to build a single solution, click the
... button and select the solution.
If you want to build multiple solutions, specify search criteria. You
can use a single-folder wildcard (*) and recursive wildcards (**).
For example, **.sln searches for all .sln files in all
subdirectories.
You can also build MSBuild project (.*proj) files. If you are building
a customized MSBuild project file, we recommend you use the MSBuild
task instead of the Visual Studio Build task.
Default value: ***.sln

Can I shrink a dotnet publish package

I have recently started developing using dotnet core (as opposed to old fashion plain .net) to create a number of small utility console applications.
The development is fine and it has come to the point I want to publish them.
I am using the CLI and as I am only interested in Win 10 deployments, tried
dotnet publish -c release -r win10-x64
It worked and built me a "publish" folder where everything seemed to work, though the "publish" folder is huge (~70mb) compared to the size of the app (~500 lines of code).
As I am only going to deploy to Win10 machines is there a way to package this so I don't need all the .NET files? I thought that was what the -r option was for but that does not seem to have achieved much.
It depends on how you want to deploy your app/who is going to use them.
The -r flag creates a self-contained app. This causes the publish command to include the necessary .NET Core DLL's for the specified platform (and platform specific nuget packages if they are avaiable), which means anyone can use the app without having to install .NET Core runtime.
If you remove the -r flag then publish will only include the DLL's for you app. But this means whoever wants to use your app must first install the .NET Core runtime.
You can see the difference by using the -o flag to write the publish output to different directories e.g.
dotnet publish -c release -r win10-x64 -o ./publish-win10
or
dotnet publish -c release -o ./publish-any
Now go and have a look at what has been written to ./publish-win10 and ./publish-any folders and you can the difference.
If you are installing them onto a system where the .NET Core runtime is already present then you can just distribute the DLL and save a lot of space. However if you want to be able to distribute the app without the end user having to worry about having the .NET Core runtime installed then the -r flag to create a self-contained distribution is the way to go, but results in the 'package' including the necessary .NET Core assemblies.
AFAIK the -r flag does not affect how you app is compiled, just what runtime DLL's are included as part of the publish command. So you always get the same DLL for your code if you publish it for win10-x64 or with, or without, the -r flag so your app DLL will run on any (.NET Core compatible) platform, but I am happy to be corrected on that point.
Unlike .NET 4.x which you are used to where building is the standard to create an output, .NET Core (And .NET 5) considers building and publishing to be very different.
The huge (70MB) size is because the publisher is assuming that your target does not have any form of the .NET Framework installed, so is bundling it in with your project.
You can change your publish line to
dotnet publish -r win-x64 --self-contained false
Just by itself, this will create the .NET Core standard - A .dll (Your application), a .exe (That runs the application), some .json files for settings, and a .pdb file for debugging symbols.
To alter the application to the .NET Framework standard output that you are used to, open the .csproj file in a text editor, and below the
<TargetFramework>netx.x</TargetFramework>
line, add
<PublishSingleFile>true</PublishSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
And rerun the publish command. This will result in a single .exe and a single .pdb in the publish directory (The .pdb file which you can safely delete).
Note: Since you have included --self-contained false, the target will need the specified version of the .NET Framework (The one specified in your .csproj file) installed. Whilst many versions of the .NET Framework are currently installed on most Windows 10 Devices (Generally located at C:\Windows\Microsoft.NET\Framework or C:\Program Files\dotnet\), the .NET Core / .NET 5 Runtimes aren't yet as common (Although will likely be distributed through Windows Update in the near future), so may require a once-off download if the recipient of your .exe does not have it.
Whilst the .NET Core / .NET 5 resultant binaries ARE larger (Although by around 150kb - Not 50MB), they run significantly faster than their .NET Framework 4.x counterparts.

.net core 2.0 console app : exe file location

I am working with .net core 2.0 console application. I need to run this console app using command prompt.
Like,
MyApp.exe arguments
I published the console app using below command to generate .exe :
dotnet publish -c Release -r win10-x64
It creates multiple .exe file,
1) \bin\Release\netcoreapp2.0\win10-x64
2) \bin\Release\netcoreapp2.0\win10-x64\publish
I believe both are same and I can use (2) as published version of the app. Correct me if wrong.
I am not sure why it generates .exe at (1) and does not contain bunch of dlls at there.
What is the difference?
anyone can give me more information about this?
The first one is still a framework-dependent deployment, it used when you call dotnet run -r win-x64. It resolves and configures the shared framework via the information in .runtimeconfig.json and your PATH environment variable and locates the DLLs via a values in the .runtimeconfig.dev.json and .deps.json based on your global packages cache (=> specific to your machine and user).
For deploying self-contained applications, the publish folder contains all the necessary assets. The host uses the local dlls instead of the shared framework and as well as the necessary DLLs.

Nuget: How to use files in the tools folder in the target application?

I have added a build EXE tool in the tools folder of my nuspec, and it is correctly added to the target application under \packages\xxx\tools folder.
But I need to invoke this file as a Build Action in the target project. What's the correct way to reference it? Bear in mind that with every new version of the package, the folder name inside \packages\ will be changed. So I cannot hardcode that.
In my case, I had this situation:
The target project was a .NET Core app.
The EXE file was not .NET Core and had to remain EXE
I invented a workaround:
Created a console app DLL project (.NET core) and added the EXE file as Embedded Resource inside it.
Created a normal NuGet package for the new DLL file.
In the target apps, I referenced this package (dll), so all future versions get updated in the normal NuGet way.
In the target app I added a post-build event to run the dll file:
dotnet TheDllName.dll
Packaged the DLL file in the normal way and referenced in the target app. In the which is dispatched in the normal way. Every time the NuGet package is updated, the new EXE will be also distributed inside the DLL. Then I used a command
What happens when the DLL runs?
Reads the EXE file from itself, like any other embedded resource.
Saves it on the disk as EXE file.
Starts a new process to run the EXE file.
Optimization
This is not absolutely necessary, but to optimize the above process, I also added a version file (simple txt file named ver.txt) to record the version number of the EXE file, so I only extract and save it once per updated NuGet package.

NuGet packages and the bin folder in ASP.NET Web Pages site

This is probably a very basic question but what's the mechanism for DLLs under the packages folder to get copied into the bin folder?
As an example, I have a solution that contains a single "project" (node) of type Web Site (i.e., no csproj, just file-system-based). It is a very basic static website. I want to add ASP.NET Web Pages support so I install this NuGet package and now there are some DLLs under the packages folder and my web.config has been updated. However, when I run the site, it shows YSOD with the error "Could not determine which version of ASP.NET Web Pages to use" which I guess is because there is no bin folder with DLLs in it (when I create a "Razor" site from scratch in Visual Studio, the bin folder is there). If I try to rebuild the solution, it fails with the same error which is compilation error (not runtime error) this time.
What's the command or mechanism to restore the bin folder from the packages folder? I don't want to have DLLs in my source control and according to NuGet docs, it seems that this workflow is very much supported. I guess that if it were csproj-based project, there would be some MS Build action or something like that to use the DLLs from the packages folder but this is a website and I cannot define advanced build actions, can I?
Using Visual Studio 2013, when I install a NuGet package, such as Microsoft.AspNet.Razor, into an ASP.NET web pages application then the bin folder is created.
Getting the binaries into the bin folder is part of the build process and it is not done by NuGet. NuGet can be used to restore the files into the packages folder but will not do anything with your bin folder when restoring.
For building and package restore to work it looks like you need to keep the bin folder and any .refresh files. You can remove the other binaries from your version control system.
System.Web.Razor.dll.refresh
The contents of this file tells Visual Studio where to find the NuGet packages:
..\..\Projects\MyWebSite\packages\Microsoft.AspNet.Razor.3.1.2\lib\net45\System.Web.Razor.dll
To test this, I deleted all the binaries from the bin folder, removed the packages folder, and then rebuilt the project. Visual Studio restores the packages and when building copies the required assemblies to the project's bin folder.

Resources