I set up my solution according to this article. I left out some of the things because according to this, ASP.NET Core 2.0 precompiles views by default. In the end, I publish it
I bet you use Self-contained deployment, i.e. publish with command like
dotnet publish --configuration Release --runtime win-x64
that results to executable file with all dependencies including .NET Core binaries.
Razor view compilation and precompilation article contains following warning:
Razor view precompilation is currently unavailable when performing a self-contained deployment (SCD) in ASP.NET Core 2.0. The feature will be available for SCDs when 2.1 releases.
So if you want to use precompiled Razor views, you should use Framework-dependent deployment, i.e. publish with the following command:
dotnet publish --configuration Release
In this case Razor views are precompiled (by default) and you will find YourAppName.PrecompiledViews.dll
among other application binaries.
UPDATE (for Precompiled Views in Library project)
My original answer relates to usual ASP.NET Core MVC application, however the question is specific to project library holding precompiled views aka Self-Contained UI.
ASP.NET Core precompiles views by default during the publish, however this is not the case for the views stored in library project. There is a github issue devoted to this problem. That discussion is pretty much long, however it ends up with the conclusion that for this moment we still need to use solution with custom targets for Razor Views precompilation. It basically the same approach as described in the article referenced by the question.
I've setup test solution with ChildApplication
and main MvcApplication
and made precompiled views working both for the build and publish.
Here is csproj for ChildApplication
(skipping sections of default ASP.NET Core MVC project):
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
</PropertyGroup>
<!-- ... -->
<Target Name="SetMvcRazorOutputPath">
<PropertyGroup>
<MvcRazorOutputPath>$(OutputPath)</MvcRazorOutputPath>
</PropertyGroup>
</Target>
<Target Name="_MvcRazorPrecompileOnBuild" DependsOnTargets="SetMvcRazorOutputPath;MvcRazorPrecompile" AfterTargets="Build" Condition=" '$(IsCrossTargetingBuild)' != 'true' " />
<Target Name="IncludePrecompiledViewsInPublishOutput" DependsOnTargets="_MvcRazorPrecompileOnBuild" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
<ItemGroup>
<_PrecompiledViewsOutput Include="$(MvcRazorOutputPath)$(MSBuildProjectName).PrecompiledViews.dll" />
<_PrecompiledViewsOutput Include="$(MvcRazorOutputPath)$(MSBuildProjectName).PrecompiledViews.pdb" />
<ContentWithTargetPath Include="@(_PrecompiledViewsOutput->'%(FullPath)')" RelativePath="%(_PrecompiledViewsOutput.Identity)" TargetPath="%(_PrecompiledViewsOutput.Filename)%(_PrecompiledViewsOutput.Extension)" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
</Target>
Here is csproj for parent MvcApplication
:
<!-- ... -->
<ItemGroup>
<ProjectReference Include="..\ChildApplication\ChildApplication.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="xcopy "$(ProjectDir)\..\ChildApplication\bin\$(ConfigurationName)\netcoreapp2.0\ChildApplication.PrecompiledViews.dll" "$(TargetDir)" /Y /I" />
</Target>
<Target Name="AddPayloadsFolder" AfterTargets="Publish">
<Exec Command="xcopy "$(ProjectDir)\..\ChildApplication\bin\$(ConfigurationName)\netcoreapp2.0\ChildApplication.PrecompiledViews.dll" "$(PublishDir)" /Y /I" />
</Target>
Dean North in his original article adds direct reference to assembly with precompiled views.
<ItemGroup>
<Reference Include="DashboardExample.PrecompiledViews">
<HintPath>..\DashboardExample\bin\Debug\netcoreapp1.1\DashboardExample.PrecompiledViews.dll</HintPath>
</Reference>
</ItemGroup>
Such approach isn't perfect because it uses assembly built with specific configuration (Debug
here). In my project file above, I use separate targets that copy ChildApplication.PrecompiledViews.dll
during the build and publish.
Here is Sample Solution on GitHub with both parent and child projects.
I usually just add these to the .csproj
. No need to copy files or any of that mess.
<PropertyGroup>
<TargetFramework>netcoreapp2.2</...
...
<MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
...
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.2.0" />
</ItemGroup>