ASP.net 5 publish output too large? - asp.net

I have a barebones ASP.net 5 web project, created from the Empty template.
I publish it in the file system. I have the folders /approot, /logs, and /wwwroot in /bin/WebsiteName/Release/PublishOutput.
The /approot folder alone is 103MB.
That seems a bit much. How to lower that?
If that is how it is, what new concepts may I might not know?

That folder has the application, its dependencies, and the runtime. Basically, everything that you need in order to run the app. Move it to another machine and it runs, nothing else needed. If the app runs on CoreCLR, there's a good chance that a big chunk of that folder is only the runtime.
Now, there are a few ways to reduce the size of the deployment package but then you'll have to get the dependencies and/or the runtime on the target server.
So, a full application, with everything would be published with dnu like this:
dnu publish --runtime <runtime1> ... --runtime <runtimeN> --no-source`
Publish only for a particular framework. If your app targets both dnxcore50 (CoreCLR) and dnx451 (Desktop CLR) you can chose to publish only one of them using dnu publish:
dnu publish --framework dnxcore50 --runtime <the framework for dnxcore50>
Don't publish the runtime. Leave the runtime out and get it somehow else on the target machine (that's what Azure WebSites does):
dnu publish (no --runtime)
I don't recommend this but if you really want you can compile the target app on the server and only publish the sources. Then you can restore (dnu restore) on the server.
Check if you really need all the packages that your app includes. For example, do you include System.Linq.Expressions but don't use it? It will be published because the publish algorithm cannot determine what's actually used.

Related

How do I integrate exe publishing with the VS2019 build of the console .net core 2.2 application?

I saw a couple of similar questions but so far I found no single answer to the problem of integrating the publishing step with my build process. Unfortunately the dotnet publish command rebuilds the project again meaning that if I put the "dotnet publish" command in the project's Post-Build steps I get an infinite loop of building retries.
What I want to achieve is to get an exe built for my .NET Core 2.2 Console App for a few selected environments eg. osx and windows-10, possibly linux too, each in its own folder. Obvious condition is that it has to be integrated with the build, so no extra manuals steps (commands) are required. This has to work from within VS2019 Pro as well in CI (like AzureDevOps).
Is this basic step achievable or .Net core was a major step-back in the progress of software development?
I hope I just miss something and I am just grossly exaggerating. :)
Thanks, Radek
How do I integrate exe publishing with the VS2019 build of the console
.net core 2.2 application?
Actually, I think you do not need to worry about this.
dotnet publish already contains the build process. Publish process will first execute Build and then run publish. In a word, Build is a part of Publish process.
So when you input dotnet publish under Build, you will get an infinite loop of building retries.
Solution
----- Just delete post-build event in xxx.csproj file and just dotnet publish directly and it will run the build process first.
You can test in the local VS and when you right-click on your project-->Publish, it will show the step in the output windwow.
In addition, as far as I know, Azure DevOps has a task called dotnet publish which contains Build.
And if you want to do some msbuild custom target only for publish step, you can add a condition like Condition="'$(DeployOnBuild)'=='true'", it will execute for Publish process rather than the normal build step(right-click on your project-->Build).
<Target Name="testone" Condition="'$(DeployOnBuild)'=='true'" AfterTargets="Build">
xxxxxxxxxxxxxx
</Target>
---------------Update 1----------------
First question
Actually, the build of the publish is the pure process and then publish will copy the content of the build output into publish folder. So the execute program is just from the build output folder.
See the publish log:
So you should not specify a publish target under the build process. This is superfluous.
Second question
To generate this program for Window-10, linux or osx, you can try these command line to publish your project:(Release is the standard release build configuration)
For Win-10:
dotnet publish -r win10-x64 -c Release --self-contained
Linux:
dotnet publish -r linux-x64 -c Release --self-contained
For osx:
dotnet publish -r osx.10.12-x64 -c Release --self-contained
In this way, the project is first built according to the specified runtime and then published.
More info about .NET Core RID Catalog, you can refer to this document.
Update 2
I think you should change the configuration in this package UI:
Then click Save.
Also, when you publish this web project, please try to delete bin and obj folder and then publish it.
Debug: bin\Debug\netcoreapp2.1\publish
Release: bin\Release\netcoreapp2.1\publish
Or you should use dotnet command as I described to publish the project. The path is under Debug or Release folder.
What I want to achieve is to get an exe built for my .NET Core 2.2
Console App for a few selected environments eg. osx and windows-10,
possibly linux too, each in its own folder. Obvious condition is that
it has to be integrated with the build, so no extra manuals steps
(commands) are required. This has to work from within VS2019 Pro as
well in CI (like AzureDevOps).
Is this basic step achievable or .Net core was a major step-back in
the progress of software development?
It's a good idea but as I know what you want is not 100% supported for now.
It seems that your expected scenario is:
Click the Build(F5) button=>Project will be built in different platforms win-x64,win-x86,linux-x64...,also will be published in different platforms automatically with self-contained mode.
But the fact is:
1.Click the Build button(Build(F5) equals to the Build button in project context) will run the Build Target (A default built-in target for each project for build). => dotnet build in command-line.
2.Click the Publish button will run the Publish Target (A default built-in target for each project for publish). => dotnet publish in command-line.
3.If you have any build/publish command in post-build event, it will result in an expected loop. So it's hard to combine publish with build perfectly since they're two actions in VS with different button/behavior/corresponding command. (Only dotnet publish command can recognize --self-contained)
4.To build/publish the projects in parallel, the batch file or msbuild targets file is a good choice.
#1.Build different platforms using one build command see this. #2.Publish different platforms using one command see this. (They both use custom .targets to do the job)
Suggestions:
According to your scenario, I think you can consider using #2. It's not necessary for you to build with different platforms during your normal development.
1.In local VS when you're developing and debugging:
The default build button/option is enough for you to debug.
2.In local VS when you want to publish the project in different platforms:
Use #2 above so that you can publish them using cmd.exe or PS.exe. (Via command dotnet msbuild -restore -t:PublishAllRids)
3.When you're automating the CI pipeline in AzDeops(Also use #2):
A CMD/PS task with dotnet msbuild -restore -t:PublishAllRids command is enough. Dotnet publish will build automatically if we don't pass --no-build argument.
4.Azure Devops Service suggests separate the jobs in different tasks, it's not recommend to Integrate Publish with Build heavily, especially for .net core projects. (Here's official sample about CI for .net core projects.)

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.

Can you create Build and Release Definitions for Website projects not Web Applications in TFS2015?

Is this possible?
We currently have build definitions and release definitions setup and working for Web Applications. However we have a lot of older web site type projects and will not work with the current build and release definitions that we already have setup.
Is there a way for us to get the web site projects to work with the build and release definitions in TFS?
Thanks
Recently changed my steps for the build definition and now that build is successful but the release still fails.
Build definition Steps are:
Nuget Installer, Copy Files, and Copy and Publish Build Artifacts
Release definition Steps are:
Powershell on Target Machines, and Windows Machine Files Copy
As web site projects needs bin folder and TFS doesn't want them to be stored in source, the best way to achieve is to convert web site projects to web application.
Best practice: Converting to web application:
https://msdn.microsoft.com/en-us/library/aa983476.aspx
But they made a workaround maybe you can try:
https://blogs.msdn.microsoft.com/tfssetup/2016/09/21/building-a-website-with-tfs-build/

using visual studio team services to build a solution containing multiple web apps and deploy these web apps to azure

My team uses Visual Studio Team Services to manage our source code in a TFS repository. The solution contains multiple web apps. I am trying to configure Continuous Integration and Continuous Deployment for this solution such that each web application is deployed to the correct Azure web app after a successful build. I've configured the BuildDefinition to build $/MyProduct/MAIN/MySolution.sln. I've defined the following parameters to MSBuild based on some MSDN articles I found on this subject:
/p:DeployOnBuild=true
/p:WebPublishMethod=Package
/p:PackageAsSingleFile=true
/p:SkipInvalidConfigurations=true
/p:PackageLocation="$(build.stagingDirectory)"
The build steps include a Visual Studio Build step, a Visual Studio Test step (currently disabled to minimize complexity), an Index Sources and Publish Symbols step (which I don't think I really need), and finally, a Copy and Publish Build Artifacts step.
I am able to build this solution using this configuration. I can see the build results, the build log, build details, etc. When I look at the artifacts that are created, I see two artifacts: "drop" and "build.sourceLabel" If I explore the drop file using the Artifacts Explorer, I find all of my projects in this drop file, and for the web app projects, I can navigate into the webapp1\obj\QA\Package\PackageTemp\bin folder and see all the DLL's etc. for the web app.
What I don't see is one zip file per web app, which is what the Release feature of Visual Studio Team Services is expecting.
I would like to know how to modify my current configuration so that I can generate the correct artifacts from the Build step so that I can create the correct Release Wep App Deployment tasks to deploy each web app to the correct web app in my environment.
This is all being done with Visual Studio 2015 and Visual Studio Online (Team Services).
To test your situation I used Visual Studio 2015 and created 3 new web projects in the same solution and checked into VSTS. I then created a new build using the Azure Website deployment template. Many people miss that we have Build and Deployment templates on the Create New Build Definition dialog. The reason I use the Azure Website template is because I can never remember the msbuild arguments to pass in. You can simply delete the Azure Web App Deployment task if you are going to use RM.
One change I always make to the msbuild arguments is the PackageLocation. I always change mine to $(BuildConfiguration). That way I can build both Debug and Release at the same time should I desire.
/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(BuildConfiguration)"
Finally I change my Copy and Publish Build Artifacts task to search for just “**\*.zip”. Leave the Copy Root empty and run your build.
When your build completes you will have one zip per project under the [ProjectName]/[Configuration]/projectName.zip when you explore your artifacts.
If you have further questions you can ping me on Twitter #DonovanBrown

ASP.NET v5 on a Build Server

I'm trying to build a VS2015 ASP.NET v5 web app on our build server (basically, outside of Visual Studio). Our existing scripts simply invoke msbuild with the csproj file, but with this project I get:
Project File is empty
What is the "story" for "building" these new webapps outside Visual Studio? I believe they can still target .NET 4.5 (I hope so, as we're not upgrading web servers any time soon) so assumed it were possible.
Well there is no .csproj in a dnx project everything that is needed for dnu to build a project is contained in the project.json. There is a xproj file but you can ignore that. Microsoft has finally decided to see the light and uses xproj just for VS specific "stuff" and IDE agnostic project details are put in the project.json.
So to build a dnx project all you need is the right version of dnx and the project source code. Now AFAIK there are no out of the box solutions but everything is done with command line commands so script something up should be easy. It all depends on how robust of a solution you want to build.
To build a dnx project from the command line (assuming you have the proper dnx installed and set to active) it is just two commands. dnu restore runs a dependency check and dnu (a part of dnx) has a built in nuget client so it will reach out and grab dependencies if needed. dnu build runs that actual compilation.
So cd to the project root (which contains project.json) and run dnu restore then dnu build.
It gets more complex if you need to dynamically support different dnx versions. Keep in mind dnx versions are identified by runtime (coreclr or clr), architecture (x86, x64, etc), and a version number. So if you are only targetting say x64 builds on clr (full .net runtime) that eliminates two variables but what happens if a project requires a newer version of the runtime than what is installed on the build server? As an example say you installed (manually using dnvm) dnx-clr-win-x64.1.0.0-beta4 on the build server but at some point in the future a developer requires dnx-clr-win-x64.1.0.0-beta6-1200 to resolve a bug.
The simplistic solution would be just to install new runtime versions as needed and build all projects against the newest one needed. This isn't as bad as it might first sound. Once dnx gets out of beta changes to the runtime should be infrequent. Remember the runtime is the very low level code and unmanaged dlls. It is the bootstrapping stub that the BCL sits on top of. Hopefully there should not be that many changes to the dnx for a given OS, architecture and runtime.
For a more robust solution you could use scripting to find the runtime version required for a project. It is found in a solution level global.json. The script could then use dnvm list to determine if it has that runtime installed. If it doesn't then use dnvm install or dnvm upgrade to install the required version. Before starting the build it would use the command dnvm use to make the correct runtime active and then proceed with dnu restore and dnu build.
Honestly I expect some pretty robust solutions to come along. Task runners (gulp, grunt, etc) are first class citizens in .NET 5. Most likely your workflow will involve bower for client side dependency resolution, npm, grunt/gulp and some task packages for things like minifying js files. The build server is going to need all that as well so having a build task as a grunt or gulp package seems a pretty good fit.

Resources