How to compile Razor views at runtime - asp.net

ASP.NET 5 MVC compiles Razor views at build time into assambly.
Some views can modifified by users after application is published.
How to include views in source code form (as cshtml files so that they can modified and compiled at runtime after modification ?
Update
Runtime compilation is enabled in Starup.cs.
Views directory does not appear in published output.
How to add Views as cshtml files so that they are compiled automatically at runtime.
Should Views directory created manually and cshtml files copied into it ? How to use those views in runtime by file name ?
How to update cshtml file in runtime and force application to use updated version?

You need to be a bit more specific with your question.
cshtml Views by default CAN be modified at runtime and do not need to be compiled for the changes to take effect,
But your question asks if they can be "compiled" at "runtime". Runtime happens after compilation, so you cannot compile at runtime.
I think the answer you're looking for is that cshtml files do not need to be compiled again if changed at runtime

Select "Enable Razor runtime compilation" while creating the project:
And here is the .csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.5" />
</ItemGroup>
</Project>

Related

How does .net core project know which files to include while building

I observed there is a difference in .csproj file in .Net standard and .Net Core.
In .Net projects all files(.cs,.js etc) were included in .csproj file for each project. e.g:
<Compile Include="ViewModel\LiveViewViewModel.cs" />
<Compile Include="ViewModel\RegistrationViewModel.cs" />
<Compile Include="Views\LiveView.xaml.cs">
<DependentUpon>LiveView.xaml</DependentUpon>
</Compile>
But if i see the new .Net Core .csproj file, there is no mention of any .cs/.js or any file.
I am very curious to understand how does .net core projects include files while being compiled.
They are now coming from msbuild definition files imported via the Microsoft.NET.Sdk MSBuild sdk and use wildcards to specify a search pattern based off the project file's location.
The (simplified) equivalent would be if you wrote
<Compile Include="**\*.cs" />
into the project file, which has been supported by msbulid for long time but didn't work well with Visual Studio tooling. The new project system can deal with wildcards much better and then add the appropriate <Compile Remove".."/> or Update=".." definition if you exclude some files or change metadata in the properties windows.
The source code for the default items be found here as well as some extra definitions brought in by the web-sdk for ASP.NET Core projects here.

How to discover .js, .css files, what are in the filesystem (and repo) but not in .csproj?

Context
I regularly make the mistake to forget include a vendor .css or .js to the Asp Mvc project. I just copy/download with a tool, or from a theme, and referencing them. All works locally because the files are in the virtual directory so IIS Express will server them.
When publish times come, and I publish the new version, those files which are not in the .csproj will not be deployed.
Question
Although some tools or itself the IDE creates warning in some cases if in a syntax construct I refer to a resource what is not in the .csproj, this is not all working (for example: when using BundleConfig)
It seems to be pretty simple prevent this source of errors: Just check the file system with a well picked filter and list all files what are not included in the .csproj. (the filter could be: (*.css, .js, ...) or (assets/.*)
How can I accomplish this task?
If you switch to the new .csproj format supported by Visual Studio 2017, you no longer need to add references to files in the file system, they are picked up by default and you have to exclude files that you don't want.
Migration to the new .csproj format is pretty straightforward - you can use the dotnet migrate tool to make the conversion.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net47</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MyProj\MyProj.csproj" />
</ItemGroup>
<ItemGroup>
<!-- /* Exclude files you don't want */ -->
<Compile Remove="Text\AnyTransliterator.cs" />
<Compile Remove="Text\BreakTransliterator.cs" />
</ItemGroup>
</Project>
If you have files outside of your project directory that you want to include, you can create a link to a file or directory.
<!-- /* Link to an individual file outside of the project */ -->
<Content Include="..\..\..\Assets\something.css" Link="Assets\something.css" />
<!-- /* Create a virtual directory in Visual Studio named Assets
and link to external Assets directory. All files in that
directory will be included in the project */ -->
<Content Include="..\..\..\Assets\**\*" LinkBase="Assets" />
<!-- /* Create a virtual directory in Visual Studio named Assets
and link to external Assets directory. Only .css files in that
directory will be included in the project */ -->
<Content Include="..\..\..\Assets\**\*.css" LinkBase="Assets" />
This works with .NET Framework, but do note that you need to install the .NET Core SDK 2.0.0 in addition to VS 2017 15.3 (and ensure no global.json selects a lower SDK version) for the LinkBase option to work.
Reference: New .csproj format - How to specify entire directory as "linked file" to a subdirectory?

.net core build produces localization folders

I have a web asp.net solution that is using .net core 2.0. I am building it using the command:
dotnet publish MySolution.sln --configuration release --output d:\test_output
But when I check the output folder, I'm seeing a lot of localization folders, as you can see in the image bellow:
Is there a way to publish the code without generating these folders?
For the projects using ASP.NET Core 3.1, add this line to your *.csproj file:
<PropertyGroup>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
</PropertyGroup>
The source of the answer in this post: Disable Dll Culture Folders on Compile.
The solution provided by #Igor.K worked for my API project, but for the ASP.NET Core MVC website in my solution, I had to make a minor change.
Try adding the line below to your .csproj file.
<PropertyGroup>
<ResourceLanguages>en</ResourceLanguages>
</PropertyGroup>
You can edit this file by right-clicking your project and selecting "Unload Project". Then, when you right-click again you will be able to edit the .csproj file. Make sure you reload the project when you're finished though.
So, if SatelliteResourceLanguages doesn't solve your problem, ResourceLanguages might do the trick.
[in net 5.0] All above solutions didn't work for me.
Out of despair I added:
<PropertyGroup>
<SatelliteResourceLanguages>en-US;en</SatelliteResourceLanguages>
</PropertyGroup>
and it worked, absolutely no idea why
On the .csproj file, you look for "Microsoft.VisualStudio.Web.CodeGeneration.Design" Package reference and add the property ExcludeAssets="All"
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" ExcludeAssets="All" />
Here is the reference: Disable Dll Culture Folders on Compile
Neither the SateliteResourceLangauges nor the ResourceLangauges solutions worked for me. In my case the files were being generated by the following nuget:
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" ExcludeAssets="All" />
Affixing ExcludeAssets="All" to it as shown above resolved the issue.

Precompiling a site for deployment using .targets file for MSBuild

I have an ASP.NET web project (.Net 4.5, Visual Studio 2015).
The solution uses the XAML builds, not the newer web builds. Some of the builds deploy the application directly to the IIS server using a file copy.
We do not use the Publish action from Visual Studio to publish the project.
In the .csproj file of the ASP.NET project, the following import statement was added to add an additional .targets file:
<Import Project="CSADeploy.targets" Condition="Exists('CSADeploy.targets')" />
<Target Name="AdditionalTargets">
<!-- ... -->
</Target>
In this target file the files are copied.
Here is a short excerpt from the .targets file:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
I would like the code that is deployed to the server to be precompiled for deployment either Deployment Only or Deployment with updateable UI is fine. I know there is a checkbox in the Publish action to precompile but I can't use that. I must use the existing XAML builds with the targets file and possibly instruction in the .csproj file.
I also know that I can use the Aspnet_compiler.exe tool on the server once the file are deployed. But I must do it before the file are copied because I do not have access to this server and I want to prevent adding a manual action to the build process.
How can I precompile the ASP.NET pages for deployment so that they are deployed correctly in my scenario?
You could create a .pubxml file for your project then check in to TFS, in the .pubxml file, set precompileBeforePublish to True.
<PropertyGroup>
......
<PrecompileBeforePublish>True</PrecompileBeforePublish>
</PropertyGroup>
In the xaml build definition, add these msbuild arguments:
/p:deployOnBuild=true /p:publishProfile=***.pubxml
Then in TFS xaml build, it will do precompile before deploy.

How is the ExcludeFromBuild itemgroup supposed to work in Web Deployment Projects?

I added an ItemGroup for ExcludeFromBuild items in the PreBuild target in my Web Deployment project:
<ItemGroup>
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Test\**\*.*" />
</ItemGroup>
After the build the assembly in the output still contains the compiled classes from the files in ~/Test. That's not what I expected.
Here is a snippet from Using Web Deployment Projects with Visual Studio 2005 on MSDN:
For example, by adding the following
section to a Web
Deployment project, you can exclude
the Test and Images folder from the
build process:
<ItemGroup>
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Test\**\*.*"/>
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Images\**\*.*"/>
</ItemGroup>
This is useful if you have test code
in the Web site project that should
not be included in the staging or
release builds.
Seems not work that way for me though. Am I missing something obvious?
Never mind, I have found the problem. The ExcludeFromBuild item group is evaluated in the _CopyBeforeBuild target, which is called before the BeforeBuild target.
Doh!

Resources