我正在尝试将ASP.NET Web应用程序部署到Azure。它是混合Web窗体,MVC和WebAPI,并且有一些TON的aspx / ascx文件,因此它们确实需要预先编译,或者每次部署都会使网站暂时缓慢。
我正在尝试通过kudu与GitHub进行SCM集成,使用预编译视图,所有这些都合并到一个程序集中。
请注意:
我已将高级预编译设置设置为:
这里是Azure的 .deployment 文件
[config]
project = WebSite/WebSite.csproj
SCM_BUILD_ARGS=/p:Configuration=Release;PublishProfile=azure-prod /v:n
您注意到我将详细程度/v
发送到"正常"有关额外的诊断信息。
以下是我对部署日志尾部的信息:
AspNetPreCompile:
D:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v \ -p D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\Source -c D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\TempBuildDir
GenerateAssemblyInfoFromExistingAssembleInfo:
Creating directory "obj\Release\AssemblyInfo".
D:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /out:obj\Release\AssemblyInfo\AssemblyInfo.dll /target:library Properties\AssemblyInfo.cs
AspNetMerge:
Running aspnet_merge.exe.
D:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\aspnet_merge.exe D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\TempBuildDir -w AppViews.dll -copyattrs obj\Release\AssemblyInfo\AssemblyInfo.dll -a
aspnet_merge : error 1003: The directory 'D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\TempBuildDir' does not exist. [D:\home\site\repository\WebSite\WebSite.csproj]
Done Building Project "D:\home\site\repository\WebSite\WebSite.csproj" (Build;pipelinePreDeployCopyAllFilesToOneFolder target(s)) -- FAILED.
Build FAILED.
看起来aspnet_compiler.exe运行,但没有做它应该做的事情,这就是为什么TempBuildDir目录(应该是编译器的输出)不及时存在的原因AspNetMerge目标。与我的系统对比,该目录实际上存在,包含标记aspx / ascx / etc.文件,静态内容,PrecompiledApp.config文件以及bin目录中的大量内容。
aspnet_compiler.exe有一个-errorstack
标记,但我不清楚如何通过.deployment
文件让MSBuild添加它,或者即使该应用程序确实是偶数抛出错误。
我可以通过Visual Studio部署,但我真的喜欢利用SCM集成,所以我可以推送到我的prod分支并放手。有什么建议吗?
答案 0 :(得分:3)
我在https://github.com/projectkudu/kudu/issues/1341回复,但是在这里复制我的答案,万一有人来到这里......
回过头来看,我们发现aspnet_compiler.exe在Azure网站中无法正常工作,因为它处理了配置文件文件夹。我们做了一个更改,但是让我们开始了:通过将HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\aspnet_compiler.exe
指向我们自己的虚拟exe(D:\Program Files (x86)\aspnet_compiler\KuduAspNetCompiler.exe
),我们把它变成了无操作。
但是现在尝试它,它似乎今天正常工作,可能要归功于Azure网站托管环境的改进。因此,我们将尝试摆脱这种黑客并进行完整的测试通过,以确保它不会导致任何重大的回归。如果一切顺利,我们可以将其投入生产,这将启用这些方案。
在短期内,您可以通过构建脚本解决此问题:
D:\Windows\Microsoft.NET\Framework\v4.0.30319
中的aspnet_compiler.exe复制到您自己的网站文件中,但名称不同(例如aspnet_compiler2.exe
)答案 1 :(得分:1)
注意:This GitHub issue on projectkudu最终会使此解决方案过时,但与此同时,该问题将作为Backlog提交,现在可以正常使用。
谢谢大卫艾伯。通过这些信息,我能够在短期内引导我的构建工作。
首先,我使用https://{WEBSITE_NAME}.scm.azurewebsites.net/DebugConsole
处提供的诊断控制台从Azure实例下载了aspnet_compiler.exe,并将其添加到我自己的存储库中。通过这种方式,32/64-bit等之间没有任何区别,我将其重命名为我的存储库中的azure_aspnet_compiler.exe
。
其次,AspNetCompiler任务没有为您提供更改工具名称的选项。它是硬编码的,但作为虚拟财产,它可以覆盖。所以我必须创建自己的任务类,并将其打包在自己的程序集中,我在发布模式下构建它,也包含在我的存储库中。
public class AzureAspNetCompiler : Microsoft.Build.Tasks.AspNetCompiler
{
private string _toolName = "aspnet_compiler.exe";
protected override string ToolName
{
get { return _toolName; }
}
public string CustomToolName // Because ToolName cannot have a setter
{
get { return _toolName; }
set { _toolName = value; }
}
}
接下来我需要替换MSBuild中的AspNetPreCompile
任务,但我无法弄清楚如何直接执行此操作。但是,无论如何,这项任务都不是 ,所以为什么不在它之后立即运行呢?
我将此添加到Website.csproj
文件的顶部以导入包含AzureAspNetCompiler
类的DLL。请注意,该路径是相对于我正在编辑的Website.csproj
文件。
<UsingTask TaskName="AzureBuildTargets.AzureAspNetCompiler"
AssemblyFile="..\DeploymentTools\AzureBuildTargets.dll" />
然后我在它下面添加了这个,这基本上是从AspNetPreCompile
窃取了C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Transform\Microsoft.Web.Publishing.AspNetCompileMerge.targets
的MSBuild目标定义,其中一些属性设置内容靠近它的顶部(因为原来的)无论如何,任务都会为我们做到这一点。)只需记下(重命名的)ToolPath
元素底部的CustomToolName
和AzureAspNetCompiler
值。
<PropertyGroup>
<!--Relative to solution root apparently-->
<LocalRepoDeploymentTools>.\DeploymentTools</LocalRepoDeploymentTools>
<AzureAspnetCompilerPath>$([System.IO.Path]::GetFullPath($(LocalRepoDeploymentTools)))</AzureAspnetCompilerPath>
</PropertyGroup>
<Target Name="NoReallyAspNetPreCompile" AfterTargets="AspNetPreCompile">
<AzureAspNetCompiler
PhysicalPath="$(_PreAspnetCompileMergeSingleTargetFolderFullPath)"
TargetPath="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)"
VirtualPath="$(_AspNetCompilerVirtualPath)"
Force="$(_AspNetCompilerForce)"
Debug="$(DebugSymbols)"
Updateable="$(EnableUpdateable)"
KeyFile="$(_AspNetCompileMergeKeyFile)"
KeyContainer="$(_AspNetCompileMergeKeyContainer)"
DelaySign="$(DelaySign)"
AllowPartiallyTrustedCallers="$(AllowPartiallyTrustedCallers)"
FixedNames="$(_AspNetCompilerFixedNames)"
Clean="$(Clean)"
MetabasePath="$(_AspNetCompilerMetabasePath)"
ToolPath="$(AzureAspnetCompilerPath)"
CustomToolName="azure_aspnet_compiler.exe"
/>
<!--
Removing APP_DATA is done here so that the output groups reflect the fact that App_data is
not present
-->
<RemoveDir Condition="'$(DeleteAppDataFolder)' == 'true' And Exists('$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\App_Data')"
Directories="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\App_Data" />
<CollectFilesinFolder Condition="'$(UseMerge)' != 'true'"
RootPath="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)" >
<Output TaskParameter="Result" ItemName="_AspnetCompileMergePrecompiledOutputNoMetadata" />
</CollectFilesinFolder>
<ItemGroup Condition="'$(UseMerge)' != 'true'">
<FileWrites Include="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\**"/>
</ItemGroup>
有了这个,一切都按照我的预期运作。