ASP.NET MVC 5发布预编译问题

时间:2017-02-07 13:55:33

标签: asp.net asp.net-mvc visual-studio web-publishing

我过去曾使用网络发布工具发布我的MVC 5应用,而不会预编译。作为我减少每个页面的初始加载时间的努力的一部分,我已经修改了我的发布设置,如下所示,以便在发布过程中预编译应用程序。突然间,我过去令人难以置信的可靠出版已成为一场噩梦。

  • 我对“将所有输出合并到单个程序集”的理解意味着我的所有.cshtml页面将被编译到Dashboard.Precompiled.dll,这将被部署到IIS。情况并非如此 - 当我能够发布工作时,它会为我项目中的每个.complied文件创建一个.cshtml文件,并且不执行任何合并。

  • 现在的主要问题是.compiled仅在某些时候生成。当我查看obj\Debug\AspnetCompileMerge\TempBuildDir\bin目录时,没有.compiled个文件,也没有Dashboard.Precompiled.dll

我尝试重新启动visual studio,清理解决方案并重新构建,预览与不在发布之前预览更改,创建全新的发布配置文件,以及一次又一次地摆弄高级预编译设置。通常在使用它30分钟后,我可以获得.precompiled文件以成功生成和发布,但是我无法确定是什么原因导致它在那段时间正常工作。下次我发布而不更改任何设置时,它将再次停止工作。使用VS2015或VS2017RC时会出现此问题。

任何人都可以请帮助我指出正确的方向吗?我已经沉溺了好几个小时,只觉得我现在已经进入了圈子。

谢谢!

修改 我仔细查看了构建输出,发现使用以下参数执行了对aspnet_compiler.exe的调用:

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

当我直接从命令行运行此命令时,.compiled中没有生成TempBuildDir\bin个文件。

enter image description here

3 个答案:

答案 0 :(得分:5)

Visual Studio使用 ASP.NET编译工具 ASP.NET合并工具来编译ASP Aspnet_compiler.exeAspnet_merge.exe。 NET应用程序。

幕后花絮VS使用这两个工具来编译Web应用程序项目。或者,您可以从命令行调用这两个工具。

您可以通过导航到此目录找到这两个文件:%WINDIR%\Microsoft.NET\Framework\v4.0.30319(或您正在使用的任何框架版本)。 您可以使用这些工具来编译ASP.NET应用程序。 要详细了解这两种工具的所有选项,请阅读以下链接:Aspnet_compiler.exeAspnet_merge.exe

我对修复问题的建议:

  • 重新启动Visual Studio
  • 清理重建您的解决方案
  • 您应该只输入没有.dll (in your example Dashboard.Precompiled.dll should be just Dashboard.Precompiled)
  • 的程序集名称
  • (您可以考虑)重新启动计算机

请在此link上详细了解有关高级预编译设置的信息,我也会在此处粘贴这些选项:

允许预编译站点可更新 - 此设置对应于aspnet_compiler.exe命令的-u选项。 如果选择此选项,则页面和用户控件(.aspx,.ascx和.master文件)将按原样复制到目标文件夹,并且可以作为文本文件进行更新,而无需重新编译项目。否则,将删除页面和用户控件的HTML标记并将其编译到程序集输出中。

发出调试信息 - 此设置对应于aspnet_compiler.exe命令的-d选项。

不合并 - 此设置不运行aspnet_merge.exe,也不使用aspnet_compiler.exe命令的-fixednames选项。

不合并。为每个页面和控件创建单独的程序集 - 此设置不运行aspnet_merge.exe。相反,它使用aspnet_compiler.exe命令的-fixednames选项。 如果要对已部署的网站进行粒度更新,则此选项很有用。但是,使用-fixednames选项进行编译会禁用编译器的批量优化,并且可能导致大型Web站点的编译时间更长。

将所有输出合并到单个程序集 - 此设置等同于aspnet_merge.exe命令的-o assemblyname选项。

视为库组件(删除App_Code.compiled文件) - 此设置对应于aspnet_merge.exe命令的-r选项。 选择此选项可以将项目的App_Code.dll程序集添加到另一个Web站点的Bin文件夹,而不会与另一个Web站点中的App_Code.dll程序集冲突。这对于构建.ascx控件库

非常有用

将每个单独的文件夹输出合并到其自己的程序集 - 此设置对应于aspnet_merge.exe命令的-prefix prefixname选项。 此选项使您可以在文件夹级别更新网站,而不是更新整个应用程序。您可以使用“可选程序集前缀”框指定一个前缀,该前缀将预先设置为所有生成的程序集名称。例如,如果指定前缀MyCompany,则名称将变为MyCompany.SubfolderName。

将所有页面和控件输出合并到单个程序集 - 此设置对应于aspnet_merge.exe命令的-w assemblyname选项。 此选项使您可以与更新其他代码分开更新UI元素。 App_Code,App_WebReferences等特殊文件夹分别编译为单独的程序集。在“程序集名称”框中指定目标程序集名称。

答案 1 :(得分:4)

请尝试以下步骤。

1。将解决方案配置更改为发布模式。

2. 确保正在发布web.config。

3. 检查web.config文件的属性,看是否将Build Action设置为None,如果是,则将其设置为Content。然后再次运行命令。

4. :仅将DashBoard.Precomiled.dll更改为DashBoard.Precomiled。

5. :同时选中视为库组件复选框。

有关这些选项的更多详情,请访问ASP.NET Compilation Tool (Aspnet_compiler.exe)

由于

答案 2 :(得分:3)

我想准确地找出之间的区别

  • “请勿合并”和“请勿合并。为每个页面和控件创建一个单独的程序集。”
    • 听起来好像它们做同样的事情,有什么区别?
  • “将所有输出合并到单个程序集中”和“将所有页面和控制输出合并到单个程序集中”
    • 同样,这些听起来像是同一件事(当您没有App_Code文件夹时)。

我想找出为什么“允许预编译站点可更新”在检查时似乎没有做任何事情(即,我认为它会在也将页面预编译为自己的程序集的同时,< / em>发出原始的可编辑*.aspx.ascx.master文件。

因此,今天,我坐下并创建了一个电子表格,并使用ASP.NET WebForms * .csproj应用程序运行了每个不同的“发布配置文件预编译”设置-我也想看看输出速度最快还是最快。

背景:

  • 我的ASP.NET项目针对.NET Framework 4.7.2
  • 这不是“网站项目”。
  • 原始C#*.cs文件未发布到生产Web服务器。
  • 这是一个使用*.aspx*.ascx*.master*.ashxGlobal.asax的WebForms项目。它不是使用Razor *.cshtml或WebForms * .aspx视图引擎的MVC项目。
  • 它不使用App_Code文件夹(因此“作为库组件处理”选项无效)。

发现:

重要提示

  • 这些发现仅在您使用“传统” ASP.NET Web Forms Web应用程序项目时适用。这些不适用于ASP.NET网站项目(您没有*.csproj文件),ASP.NET MVC(非核心)项目或ASP.NET Core项目。
  • 我使用术语“页面文件”作为*.aspx*.ascx*.master*.asmx*.ashx文件的简写,但是不是 Global.asax
  • 我使用术语“正常构建”来表示在Visual Studio中执行“构建>重建项目”,您可以在%projectdir%\bin目录中看到输出。相比之下,进行发布构建(将首先执行常规构建,然后将输出复制到另一个目录以运行发布MSBuild步骤)

以下是我对每个选项产生的结果的发现:

  • “发布时预编译”(在“发布设置”窗口中)

    • 如果您没有App_Code文件夹,并且要发布可编辑的*.aspx / *.ascx /`* .master文件,则无需检查性能此框
      • 这是因为,当选中此选项但未选中“允许预编译的站点可更新”时,它将仅预编译您的Global.asax文件(而不是Global.asax.cs)仍然可以编译。)
      • 即您的*.aspx*.ascx*.master*.ashx文件将被预编译为程序集,并且仍然需要在它们上进行编译Web服务器上的需求。
      • 但是它仍将对其进行预编译,以检查<% @*.aspx*.ascx*.master*.asax中的编译器错误和*.ashx行是否损坏*.aspx个文件。
  • “允许预编译站点可更新”

    • 当选中此选项时,您的*.ascx*.master*.ashx*.aspx文件将被预编译为程序集,它们将仍然需要在Web服务器上按需编译。
      • 我本来以为它将这些文件预编译为程序集(DLL),并另外将原始*.pdb文件发布在服务器上进行编辑,并且仅在它们被更改时才重新编译-但我错了。 / li>
  • 发出调试信息

    • 这将为预编译过程生成的每个新程序集生成*.pdb文件。它不会不会影响正常构建您的应用程序时已经存在的任何App_Code文件。
    • 我认为应该始终启用该功能-PDB文件对于快速调查运行时问题至关重要,并且它们不会增加最终发布的大小。
  • 请勿合并

    • 如果您没有Global.asax文件夹,并且选中“允许预编译的站点可更新”,则“不合并”将仅将App_global.asax.dll完全预编译为{{1} }。没有其他DLL文件将被添加到最终的发布输出中。

    • 如果未选中“允许预编译的站点可更新”,则所有 Page文件(在上面的“重要说明”下定义)都将被编译为新的DLL文件App_Web_xxxxxxxx.dll每班10个班级。

      • 我看不到它是如何决定将文件使用哪种模式进行分组的10个文件-有时它们是按字母顺序排列的,有时是任意的。
  • 不合并。为每个页面和控件创建一个单独的程序集。

    • 与上面相同,除了不是每个程序集以10个 Page文件(或类)为一组,而是每个程序集1- Page文件
    • 当未选中“允许预编译的站点可更新”时,这也是发布速度最慢的版本之一。
    • 此方法的唯一优点是,如果您要单独替换服务器上每个页面的预编译*.dll-但我认为这不是一个好主意,因为它经常会损坏-最好替换所有文件立刻。仅当您使用56K连接并且一次只能上传少于100KB的数据时,才执行此操作-这真是愚蠢。
  • 将所有输出合并到单个程序集中

    • 确实确实将所有 Page文件 Global.asaxApp_global.asax.dll)编译/合并为单个DLL文件。
  • 将其作为库组件

    • 此选项对我的项目(无论是选中还是未选中)无效(因为我的项目没有App_Code文件夹)。
  • 将每个单独的文件夹输出合并到其自己的程序集中

    • 这会为包含 Page文件的项目中的每个文件系统目录生成中间DLL,然后将它们合并为每个文件夹的单个DLL。
    • 此选项导致发布构建时间第二长。
    • 我想不出今天为什么需要使用此功能的充分理由-除非您的项目中有成千上万个 Page文件分布在数十个文件夹中并且想要进行手动增量更新。 (即,这不是您在CI / CD流程中使用的选项)。
  • 将所有页面和控制输出合并到单个程序集中

    • 如果您有App_Code文件夹:
      • 然后,App_Code(以及其他App_GlobalResourcesApp_WebReferences之类的“特殊文件夹”)的内容将从您的 Page文件预编译到该单独的程序集中部件。这将包括Global.asax(编译为App_global.asax.dll)。
    • 如果您没有App_Code文件夹,则此选项的输出与“将所有输出合并到单个程序集”非常相似,除了最终输出会将Global.asax预编译为它自己的程序集( App_global.asax.dll)。
      • 此选项导致所有选项的发布生成时间最长-在我的情况下为零实际收益。
      • 因此,如果您没有App_Code文件夹,则没有理由选择此选项。

已重定:

选中“允许预编译站点可更新”并选中“不合并”时:

*.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`

未选中“允许预编译站点可更新”并且选中“不合并”时:

*.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`

未选中“允许预编译站点可更新”并且选中“将每个单独的文件夹输出合并到其自己的程序集中”时:

*.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`

当未选中“允许预编译的站点可更新”并且选中了“将所有输出合并到单个程序集(命名为“所有内容”)”时:

*.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

未选中“允许预编译站点可更新”并且选中“将每个单独的文件夹输出合并到其自己的程序集中”时:

*.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`

选中“将所有页面和控件输出合并到单个程序集(名为'PagesAndControls')”时

*.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`

结论:

如果部署后无需编辑*.aspx / *.ascx,/ *.master文件,并且您没有App_Code文件夹,然后选择以下设置以获得最佳效果:

[ ] Allow precompiled site to be updatable
[X] Emit debug information
[X] Merge all outputs to a single assembly 
[ ] Treat as library component

方法:

  • 所有版本都使用Release。
  • 使用了“文件夹”发布配置文件。
    • 目标是同一磁盘卷(PCI-Express Optane驱动器)上的文件夹。
    • 每次运行后,该文件夹均已清除。
  • 每次测试之间的唯一变化是更改了
  • 中的参数
  • git确认在每次构建和发布之前对源文件和项目文件的零更改。
  • 我运行了一个Shell脚本,该脚本在每次运行之间完全清除了binobj目录,因此在运行之间完全重建了Web应用程序项目,而不仅仅是Publish)。
  • 我使用了一个Stopwatch程序来记录我单击“发布”按钮的确切时间,但是当我看到“发布”操作完成时被键盘按下手动停止了。

结果:

(我的电子表格的屏幕截图)

Screenshot of Excel spreadsheet of precompilation input options and observed output