I have used the web publishing tool to publish my MVC 5 app in the past without precompiling in the past. As part of my effort to reduce the initial load time for each page, I have modified my publish settings as shown below to precompile the app during the publish process. All of a sudden, the incredibly reliable publishing that I was used to has become a nightmare.
My understanding of the "Merge all outputs to a single assembly" would mean that all of my .cshtml
pages would get compiled together into Dashboard.Precompiled.dll
, which would get deployed to IIS. This has not been the case - when I am able to get publishing to work, it creates a .complied
file for each .cshtml
file in my project and does not perform any merging.
The major issue right now is that the .compiled
are only generated some of the time. When I look in the obj\Debug\AspnetCompileMerge\TempBuildDir\bin
directory there are no .compiled
files nor Dashboard.Precompiled.dll
.
I have tried restarting visual studio, cleaning the solution and rebuilding, previewing vs. not previewing the changes before publish, creating a brand new publish profile, and fiddling with the advanced precompile settings time and time again. Usually after 30 minutes or so of mucking with it I can get the .precompiled
files to generate and publish successfully, however I have not been able to identify what caused it to work correctly that time. The next time I go and publish without changing any settings, it will stop working again. The issue occurs when using either VS2015 or VS2017RC.
Can anyone please help point me in the right direction here? I've sunk many hours into this already and just feel like I'm going in circles at this point.
Thanks!
EDIT I took a closer look at the build output and found the call to aspnet_compiler.exe was executed with the following parameters:
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v / -p C:\Users\steve\Source\Dashboard\master\src\Agility.Web\obj\Staging\AspnetCompileMerge\Source -d C:\Users\steve\Source\Dashboard\master\src\Agility.Web\obj\Staging\AspnetCompileMerge\TempBuildDir
When I run this command directly from the command line, no .compiled
files are being generated in TempBuildDir\bin
.
I wanted to find out exactly what the differences were between:
App_Code
folder).And I want to find out why "Allow precompiled site to be updatable" didn't seem to do anything when it was checked (i.e. I thought it would precompile the pages to their own assembly/assemblies while also emitting the original editable *.aspx
, .ascx
, .master
files.
So, today I sat-down and created a spreadsheet and ran every different Publish Profile Precompilation setting with an ASP.NET WebForms *.csproj application - I also wanted to see what was the slowest vs. quickest output.
*.cs
files are not published to the production web-server.*.aspx
, *.ascx
, *.master
, *.ashx
and Global.asax
. It is not an MVC project using the Razor *.cshtml
nor WebForms *.aspx
view-engines).App_Code
folder (so the "Treat as library component" option has no effect).Important notes:
*.csproj
file), ASP.NET MVC (non-Core) projects, nor ASP.NET Core projects.*.aspx
, *.ascx
, *.master
, *.asmx
, and *.ashx
files, but not Global.asax
.%projectdir%\bin
directory. This is compared to doing a Publish Build (which will perform a normal build first, then copy the output to another directory to run the Publish MSBuild steps)Here are my findings for what each option results in:
"Precompile during publishing" (in Publish Settings window)
App_Code
folder and you want to publish editable *.aspx
/*.ascx
/`*.master files then there is no performance reason to check this box.
Global.asax
file (not your Global.asax.cs
, which is compiled anyway).*.aspx
, *.ascx
, *.master
and *.ashx
files will not be precompiled to an assembly, and they'll still need to be compiled on-demand on the web-server.<% @
-lines in your *.aspx
, *.ascx
, *.master
, *.asax
and *.ashx
files."Allow precompiled site to be updatable"
*.aspx
, *.ascx
, *.master
and *.ashx
files will not be precompiled to an assembly, and they'll still need to be compiled on-demand on the web-server.
*.aspx
files for editing on the server and only recompile them if they're changed - but I was wrong.Emit debug information
*.pdb
files for each new assembly generated by the precompilation process. It does not affect any *.pdb
files already present when your application is built normally.Do not merge
When you don't have an App_Code
folder and "Allow precompiled site to be updatable" is checked then "Do not merge" will only fully precompile Global.asax
into App_global.asax.dll
. No other DLL files will be added to the final publish output.
When "Allow precompiled site to be updatable" is unchecked then all Page files (defined under "Important notes" above) will be compiled into new DLL files App_Web_xxxxxxxx.dll
in groups of 10 classes.
Do not merge. Create a separate assembly for each page and control.
*.dll
on the server - but I don't think that's a good idea as it will often break - it's better to replace all files at once. Only do this if you're on a 56K connection and can only upload less than 100KB at a time - which is just silly.Merge all outputs to a single assembly
Global.asax
(App_global.asax.dll
) to a single DLL file.Treat as library component
App_Code
folder).Merge each individual folder output to its own assembly
Merge all pages and control outputs to a single assembly
App_Code
folder:
App_Code
(and other "Special folders" like App_GlobalResources
, App_WebReferences
) will be precompiled to this separate assembly from your Page files assembly. This will not include Global.asax
(compiled to App_global.asax.dll
).App_Code
folder then this option results in very similar output to "Merge all outputs to a single assembly" except the final output will precompile Global.asax
to its own assembly (App_global.asax.dll
).
App_Code
folder then there is no reason to choose this option.Restated:
When "Allow precompiled site to be updatable" is checked and "Do not merge" is checked:
*.aspx
*.ascx
*.ashx
*.asmx
*.master
* Compiled only for error-checking.
* Not compiled to an assembly DLL in the `bin\` folder.
Global.asax
* Compiled to `App_global.asax.dll`
App_Code
* Compiled to `App_Code.dll`
When "Allow precompiled site to be updatable" is not checked and "Do not merge" is checked:
*.aspx
*.ascx
*.ashx
*.asmx
*.master
* Compiled to `App_Web_abcdefghij.dll` in groups of 10-per-DLL
Global.asax
* Compiled to `App_global.asax.dll`
App_Code
* Compiled to `App_Code.dll`
When "Allow precompiled site to be updatable" is not checked and "Merge each individual folder output to its own assembly" is checked:
*.aspx
*.ascx
*.ashx
*.asmx
*.master
* Each file compiled to its own `App_Web_OriginalFileName.abcdefghij.dll` file.
Global.asax
* Compiled to `App_global.asax.dll`
App_Code
* Compiled to `App_Code.dll`
When "Allow precompiled site to be updatable" is not checked and "Merge all outputs to a single assembly (named 'Everything')" is checked:
*.aspx
*.ascx
*.ashx
*.asmx
*.master
* Compiled and merged into the single Everything.dll
Global.asax
* Compiled and merged into the single Everything.dll
App_Code
* Compiled and merged into the single Everything.dll
When "Allow precompiled site to be updatable" is not checked and "Merge each individual folder output to its own assembly" is checked:
*.aspx
*.ascx
*.ashx
*.asmx
*.master
* Compiled into an assembly for each folder.
Global.asax
* Compiled to `App_global.asax.dll` (separate from the assembly for the *.aspx files in the root directory)
App_Code
* Compiled and merged into `App_Code.dll`
When "Merge all pages and control outputs to a single assembly (named 'PagesAndControls')" is checked:
*.aspx
*.ascx
*.ashx
*.asmx
*.master
* Compiled into PagesAndControls.dll
Global.asax
* Compiled to `App_global.asax.dll` (separate from PagesAndControls.dll)
App_Code
* Compiled and merged into `App_Code.dll`
If you don't need to edit *.aspx
/*.ascx
,/*.master
files once they're deployed, and you don't have an App_Code
folder, then choose these settings for the best results:
[ ] Allow precompiled site to be updatable
[X] Emit debug information
[X] Merge all outputs to a single assembly
[ ] Treat as library component
git
confirmed zero changes to source files and project files before each build and publish.bin
and obj
directories between each run, so the web-application project is fully rebuilt between runs instead of just the Publish).(Screenshot of my spreadsheet)
Visual Studio uses ASP.NET compilation tool and ASP.NET merging tool which are the Aspnet_compiler.exe
and Aspnet_merge.exe
to compile an ASP.NET application.
Behind the scenes VS uses these 2 tools to compile web applications projects. Alternatively, you can invoke these 2 tools from the command line.
You can locate these 2 files by navigating to this directory: %WINDIR%\Microsoft.NET\Framework\v4.0.30319
(or to whatever framework version you are using).
You can use these tools to compile ASP.NET applications.
To learn more about all options of these 2 tools please read these links: Aspnet_compiler.exe and Aspnet_merge.exe
My recommendation on fixing the issue:
(in your example Dashboard.Precompiled.dll should be just Dashboard.Precompiled)
Please read more about Advanced Precompile settings on this link, I'm pasting here the options as well:
Allow precompiled site to be updatable - This setting corresponds to the –u option of the aspnet_compiler.exe command. If you select this option, pages and user controls (.aspx, .ascx, and .master files) are copied as-is to the target folder and can be updated as text files without recompiling the project. Otherwise, the HTML markup for pages and user controls is removed and compiled into the assembly output.
Emit debug information - This setting corresponds to the -d option of the aspnet_compiler.exe command.
Do not merge - This setting does not run aspnet_merge.exe and does not use the -fixednames option of the aspnet_compiler.exe command.
Do not merge. Create a separate assembly for each page and control - This setting does not run aspnet_merge.exe. Instead, it uses the -fixednames option of the aspnet_compiler.exe command. This option is useful if you want to make granular updates of your deployed web site. However, compiling with the -fixednames option disables the compiler's batch optimizations and can result in longer compile times for large web sites.
Merge all outputs to a single assembly - This setting is equivalent to the -o assemblyname option of the aspnet_merge.exe command.
Treat as library component (remove the App_Code.compiled file) - This setting corresponds to the -r option of the aspnet_merge.exe command. Selecting this option enables the project's App_Code.dll assembly to be added to the Bin folder of another web site without conflicting with the App_Code.dll assembly in the other web site. This is useful for building a library of .ascx controls
Merge each individual folder output to its own assembly - This setting corresponds to the -prefix prefixname option of the aspnet_merge.exe command. This option enables you to update your web site at the folder level rather than updating the entire application. You can use the Optional assembly prefix box to specify a prefix that will be pre-pended to all generated assembly names. For example, if you specify the prefix MyCompany, the name becomes MyCompany.SubfolderName.
Merge all pages and control outputs to a single assembly - This setting corresponds to the –w assemblyname option of the aspnet_merge.exe command. This option enables you to update UI elements separately from updating other code. Special folders such as App_Code, App_WebReferences, and so on are each compiled into a separate assembly. Specify the target assembly name in the Assembly name box.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With