I'm using Aspnetboilerplate framework in my Web project.
Everything was working until I noticed that my production environment was very slow on first page access.
Doing some researchs I discovered that the problem was to not pre compile cshtml views on build. So, in my vsts build definition I added the follow:
/p:PrecompileBeforePublish=true /p:UseMerge=true /p:SingleAssemblyName=AppCode
But now I'm getting the follow error on all my cshtml views:
Seduca.Web\obj\Release\AspnetCompileMerge\Source\App\Main\views\aulas\index.cshtml(5,0): Error CS0103: The name 'IsGranted' does not exist in the current context
Works if I put this on top of each view:
#inherits Seduca.Web.Views.SeducaWebViewPageBase
but it looks like my file (web.config) is being ignored.
My .csproj looks like this:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MvcBuildViews>true</MvcBuildViews>
<LangVersion>6</LangVersion>
</PropertyGroup>
...
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<ItemGroup>
<ExtraWebConfigs Include="$(BaseIntermediateOutputPath)\**\web.config" />
<ExtraPackageTmp Include="$([System.IO.Directory]::GetDirectories("$(BaseIntermediateOutputPath)", "PackageTmp", System.IO.SearchOption.AllDirectories))" />
</ItemGroup>
<Delete Files="#(ExtraWebConfigs)" />
<RemoveDir Directories="#(ExtraPackageTmp)" />
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
And the web.config:
The error only happens in vsts build. In local deploy, (with release option and precompile) it works.
I've tried with hosted and private agents on vsts.
The issue appears to be that you are not adding the namespaces to the correct Web.config file. .cshtml files get their globally imported namespaces from the Views\Web.config file, not the root Web.config file.
The information you have in the root Web.config file is correct, you just need to move it to the Views\Web.config file.
Related
I have tried about twenty solutions I have found online on how to prevent appsettings.{somevalue}.json from being published with the wrong environment. Basically I have a "development" variant and "production" variant and both are set to Copy If Newer under properties in the project. I have 2 publish profiles publishing a Worker Service app to a remote directory, one for debug configuration to my development environment (where the DOTNET_ENVIRONMENT is set to Development) and one to a similar production environment. I want to exclude the opposite environments config file from the publish or build automatically. Simple solution is to delete the file myself, however I want to make sure this is automated when published. Part of the issue is the complete lack of information on what goes in these pubxml files or csproj file that allows you to remove or delete files. Other questions on stack exchange have noted this lack of information as well.
Here is what I have recently tried and I have tried placing these blocks in both pubxml files and csproj file both inside and outside of the PropertyGroup node but none of these work:
1.
<Target Name="Debug" AfterTargets="AfterPublish">
<Message Text="Development Publish Message"></Message>
<Delete Files="appsettings.Production.json" />
</Target>
(I have also tried specifying variables for that json file's location as well as hardcoding its actual path in the final publish. This does nothing and that message isn't shown anywhere)
2.
<ItemGroup>
<Content Remove="appsettings.Production.json" />
</ItemGroup>
<ExcludeFilesFromDeployment>
bin\Debug\netcoreapp3.1\appsettings.Production.json;
</ExcludeFilesFromDeployment>
<ItemGroup>
<Content Update="appsettings.Production.json" CopyToPublishDirectory="Never" />
</ItemGroup>
(this one is straight from Microsoft but like many others, does nothing)
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/visual-studio-publish-profiles?view=aspnetcore-6.0
<Choose>
<When Condition="'$(Configuration)' == 'Debug'">
<ItemGroup>
<None Include="appsettings.Production.json" CopyToOutputDirectory="Never" CopyToPublishDirectory="Never" />
</ItemGroup>
</When>
<When Condition="'$(Configuration)' == 'Release'">
<ItemGroup>
<None Include="appsettings.Development.json" CopyToOutputDirectory="Never" CopyToPublishDirectory="Never" />
</ItemGroup>
</When>
</Choose>
I could continue but nothing I have found works. Is this even possible?
Thanks!
Visual Studio 2019, .Net Standard 2.0
How do I include a custom msbuild targets file for the consuming project?
What is the official supported way of doing this?
I've already tried:
modifying the csproj file as per (Setting Nuget package target path for item in MSBuild project)
trying to specify a nuspec file as per (https://natemcmaster.com/blog/2017/11/11/build-tools-in-nuget/)
Nuspec:
<?xml version="1.0"?>
<package >
<metadata>
<id>TestingNugetContent</id>
<version>1.0.10</version>
<title>Blah</title>
<authors>Me</authors>
<owners>Me</owners>
<licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
<projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Blah</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2019</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="Immutable\*.*" target="content/Immutable/" />
<file src="Build\*.*" target="build/netstandard2.0/" />
</files>
</package>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<NoPackageAnalysis>true</NoPackageAnalysis>
<NuspecFile>TestingNugetContent.nuspec</NuspecFile>
<IntermediatePackDir>$(MSBuildProjectDirectory)/bin/$(Configuration)/publish/</IntermediatePackDir>
<PublishDir>$(IntermediatePackDir)$(TargetFramework)/</PublishDir>
<NuspecProperties>publishDir=$([MSBuild]::NormalizeDirectory($(IntermediatePackDir)))</NuspecProperties>
<Version>1.0.10</Version>
</PropertyGroup>
<ItemGroup>
<Compile Remove="build\**" />
<EmbeddedResource Remove="build\**" />
<None Remove="build\**" />
</ItemGroup>
<ItemGroup>
<None Include="build\netstandard2.0\TestingNugetContent.targets" />
</ItemGroup>
<Target Name="PublishAll" BeforeTargets="GenerateNuspec">
<ItemGroup>
<_TargetFramework Include="$(TargetFrameworks)" />
</ItemGroup>
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Publish" Properties="TargetFramework=%(_TargetFramework.Identity)" />
</Target>
</Project>
Checking the consumer's <***>.csproj.nuget.g.targets file the import project tag for this custom target is missing after installing the Nuget package
As per the docs, the props and targets file names must match the package id exactly. Your nuspec lists the <id> as TestingNugetContent, so the files must be TestingNugetContent.props and TestingNugetContent.targets. They should be either directly in the build/ folder in the package, or the build/<tfm>/ folder (I prefer to be more explicit, so I appriciate you used the netstandard2.0 TFM). Now, your csproj appears to specify a build\netstandard2.0\TestingNugetContent.targets, which looks correct, so I can only guess that it wasn't packed into the correct location somehow.
I don't currently have time to show an example on how to pack it, but you can inspect the contents of your nupkg using NuGet package explorer, or just opening it up as a zip file, see what's "wrong", then adjust your project and try again.
FYI, you shouldn't need to use a nuspec at all, you can use the MSBuild PackagePath metadata on items to specify where MSBuild items are packed. It's unclear to me what the purpose of your PublishAll target is supposed to be. If you added it as part of trying to get your targets file included, you can remove it.
I have several MVC projects in one solution.
Following this accepted answer: "Add as Link" for folders in Visual Studio projects, I am attempting to reuse .cshtml views across these proejcts by placing reusable views in a base project. So far, I have set up location formats in the "consuming" projects for the view-engine like this:
var locationFormats = new string[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Common/{1}/{0}.cshtml",
"~/Views/Common/Shared/{0}.cshtml"
};
I have set up a recursive, linked directory in consuming projects' .csproj files to include common views like this:
<ItemGroup>
<Content Include="..\..\..\common.cms\CommonViews\**\*.*">
<Link>\Views\Common\%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
...and all the views are appearing in the consuming projects with the linked-file/cshtml(#) icon, so the paths are correct. For example, the following file is very clearly present in my test consuming project:
\Views\Common\Home\Index.cshtml
But when I run the project, I'm getting:
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.cshtml
~/Views/Shared/Index.cshtml
~/Views/Common/Home/Index.cshtml
~/Views/Common/Shared/Index.cshtml
Question
So I am wondering: is it even possible to link views in this way? What is missing, or what could be inhibiting this from working?
More generally, what about any non-compiled files I'd like to share? Is this technique never going to work?
I've found that this as a known bug in visual studio: Linked files in Web Application projects are not deployed properly. This goes back to VS-2008 but still affects VS-2010 and 2012 (not sure about 2013).
A workaround is detailed in this blog-post:
Using Linked Files with Web Application Projects.
If you just want the fix wihtout the explanation, you just need to paste the code below at the end of the .csproj file for your project (just before the closeing </project> tag). This will fix the problem for any linked, un-compiled files:
<!--
============================================================
_CopyWebApplication
MODIFIED: Ignores linked files as part of normal deployment logic.
This target will copy the build outputs along with the
content files into a _PublishedWebsites folder.
This Task is only necessary when $(OutDir) has been redirected
to a folder other than ~\bin such as is the case with Team Build.
============================================================
-->
<Target Name="_CopyWebApplication" Condition="'$(OutDir)' != '$(OutputPath)'">
<!-- Log tasks -->
<Message Text="Copying Web Application Project Files for $(MSBuildProjectName)" />
<!-- Create the _PublishedWebsites\app\bin folder -->
<MakeDir Directories="$(WebProjectOutputDir)\bin" />
<!-- Copy build outputs to _PublishedWebsites\app\bin folder -->
<Copy SourceFiles="#(IntermediateAssembly)"
DestinationFolder="$(WebProjectOutputDir)\bin"
SkipUnchangedFiles="true" />
<Copy SourceFiles="#(AddModules)"
DestinationFolder="$(WebProjectOutputDir)\bin"
SkipUnchangedFiles="true" />
<Copy SourceFiles="$(IntermediateOutputPath)$(_SGenDllName)"
DestinationFolder="$(WebProjectOutputDir)\%(Content.SubFolder)%(Content.RecursiveDir)"
SkipUnchangedFiles="true"
Condition="'$(_SGenDllCreated)'=='true'" />
<Copy SourceFiles="$(IntermediateOutputPath)$(TargetName).pdb"
DestinationFolder="$(WebProjectOutputDir)\bin"
SkipUnchangedFiles="true"
Condition="'$(_DebugSymbolsProduced)'=='true'" />
<Copy SourceFiles="#(DocFileItem)"
DestinationFolder="$(WebProjectOutputDir)\bin"
SkipUnchangedFiles="true"
Condition="'$(_DocumentationFileProduced)'=='true'" />
<Copy SourceFiles="#(IntermediateSatelliteAssembliesWithTargetPath)"
DestinationFiles="#(IntermediateSatelliteAssembliesWithTargetPath->'$(WebProjectOutputDir)\bin\%(Culture)\$(TargetName).resources.dll')"
SkipUnchangedFiles="true" />
<Copy SourceFiles="#(ReferenceComWrappersToCopyLocal); #(ResolvedIsolatedComModules); #(_DeploymentLooseManifestFile); #(NativeReferenceFile)"
DestinationFolder="$(WebProjectOutputDir)\bin"
SkipUnchangedFiles="true" />
<!-- copy any referenced assemblies to _PublishedWebsites\app\bin folder -->
<Copy SourceFiles="#(ReferenceCopyLocalPaths)"
DestinationFolder="$(WebProjectOutputDir)\bin"
SkipUnchangedFiles="true" />
<!-- MODIFICATION HERE: Copy local content files (i.e. non-linked files) recursively to _PublishedWebsites\app\ folder -->
<Copy Condition=" '%(Content.Link)' == '' "
SourceFiles="%(Content.Identity)"
DestinationFolder="$(WebProjectOutputDir)\%(Content.RelativeDir)" />
</Target>
<!--
============================================================
CopyLinkedContentFiles
A new target to copy any linked content files into the
web application output folder.
NOTE: This is necessary even when '$(OutDir)' has not been redirected.
============================================================
-->
<Target Name="CopyLinkedContentFiles">
<!-- Remove any old copies of the files -->
<Delete Condition=" '%(Content.Link)' != '' AND Exists('$(WebProjectOutputDir)\%(Content.Link)') "
Files="$(WebProjectOutputDir)\%(Content.Link)" />
<!-- Copy linked content files recursively to the project folder -->
<Copy Condition=" '%(Content.Link)' != '' "
SourceFiles="%(Content.Identity)"
DestinationFiles="$(WebProjectOutputDir)\%(Content.Link)" />
</Target>
<!-- Override the default target dependencies to -->
<!-- include the new _CopyLinkedContentFiles target. -->
<PropertyGroup>
<PrepareForRunDependsOn>
$(PrepareForRunDependsOn);
_CopyWebApplication;
CopyLinkedContentFiles;
_BuiltWebOutputGroupOutput
</PrepareForRunDependsOn>
</PropertyGroup>
In my Asp.Net MVC 4 project, I've set in the .csproj file to build the view <MvcBuildViews>true</MvcBuildViews>. The problem is that building the project I got the error:
It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.
I tried to delete the obj folder but the error keep raising. The error specify that the problem is in the authentication tag row:
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
Often, I'm able to run the application by running the application (I got the error), building the app and after that running again.
Doing what #matrixugly suggests will fix the issue, but will also cause the compile-time view checking to stop working as well. I am assuming you still want to error check your views at compile time? If that is the case, better fixes below.
In order to understand why these solutions work, we have to first know how the problem is created:
The developer wants compile-time checking on views, so they set MvcBuildViews=true.
The application builds fine, UNTIL they publish the project.
Subsequent attempts to build the project result in a compile-time error: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.
So what causes this issue? When the project is published the compiler, by default it uses <project-dir>\obj\ to place copies of the source files that it will work with. Unfortunately, these files are not automatically deleted when publishing is complete. The next time the developer compiles the project with MvcBuildViews=true, it will error out because the aspnet compiler includes the obj\ folder during compilation, since it is underneath the <project-dir> folder.
So how do we fix this? Well, you have four options:
Set MvcBuildViews=false. I don't really consider this a solution, so let's move on.
Delete the files in <project-dir>\obj\. Works, but can be a hassle since it has to be done after every publish.
Change the path that publishing uses as an intermediate directory through the use of the <BaseIntermediateOutputPath> property in your project config file.Example (Ref: this link):
<BaseIntermediateOutputPath>
[SomeKnownLocationIHaveAccessTo]
</BaseIntermediateOutputPath>
Add a new section in your project config file that deletes the offending files for you on build (reference Microsoft Connect). I've even made it easy for you, just copy and paste:
<PropertyGroup>
<_EnableCleanOnBuildForMvcViews Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='' ">true</_EnableCleanOnBuildForMvcViews>
</PropertyGroup>
<Target Name="CleanupForBuildMvcViews" Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='true' and '$(MVCBuildViews)'=='true' " BeforeTargets="MvcBuildViews">
<ItemGroup>
<_TempWebConfigToDelete Include="$(BaseIntermediateOutputPath)**\Package\**\*" />
<_TempWebConfigToDelete Include="$(BaseIntermediateOutputPath)**\TransformWebConfig\**\*" />
<_TempWebConfigToDelete Include="$(BaseIntermediateOutputPath)**\CSAutoParameterize\**\*" />
<_TempWebConfigToDelete Include="$(BaseIntermediateOutputPath)**\TempPE\**\*" />
</ItemGroup>
<Delete Files="#(_TempWebConfigToDelete)"/>
</Target>
My recommendation would be to use either option 3 or 4.
N.B. For those that have never edited their project file, you can't edit it while loaded. It must first be unloaded by right clicking it and selecting Unload Project. You can then right-click the project and edit the project file. Alternatively, you can edit the file outside of Visual Studio.
I had the exact same problem when trying to publish my web application after enabling MvcBuildViews to validate my Razor syntax
I found this code in my web config
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
Try commenting it out, so that the compiler behavior is not changed
<!--<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>-->
#newmanth answer is excellent, but outdated. Year 2022 and let me tell you - this CleanupForBuildMvcViews is actually oficially included within C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.targets! :)
It even features the link to (now broken) Microsoft Connect as #newmanth references.
Here is the snippet:
<!--Deal with http://connect.microsoft.com/VisualStudio/feedback/details/779737/error-allowdefinition-machinetoapplication-beyond-application-level,
we will need to clean up our temp folder before MVC project starts the pre-compile-->
<PropertyGroup>
<_EnableCleanOnBuildForMvcViews Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='' ">true</_EnableCleanOnBuildForMvcViews>
</PropertyGroup>
<Target Name="CleanupForBuildMvcViews" Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='true' and '$(MVCBuildViews)'=='true' " BeforeTargets="MvcBuildViews">
<ItemGroup>
<_PublishTempFolderNamesToCleanup Include="Database;TransformWebConfig;CSAutoParameterize;InsertAdditionalCS;ProfileTransformWebConfig;Package" />
</ItemGroup>
<!--Force msbuild to expand all the wildcard characters so to get real file paths-->
<CreateItem Include="#(_PublishTempFolderNamesToCleanup->'$(BaseIntermediateOutputPath)**\%(identity)\**\*')">
<Output TaskParameter="Include" ItemName="_EvaluatedPublishTempFolderNamesToCleanup" />
</CreateItem>
<Delete Files="#(_EvaluatedPublishTempFolderNamesToCleanup)" />
</Target>
However I still get the said exception. In my Case I had to delete AspnetCompileMerge folder too. And name Target in another name, not to overwrite it:
<PropertyGroup>
<_EnableCleanOnBuildForMvcViews Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='' ">true</_EnableCleanOnBuildForMvcViews>
</PropertyGroup>
<Target Name="CleanupForBuildMvcViews2" Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='true' and '$(MVCBuildViews)'=='true' " BeforeTargets="MvcBuildViews">
<ItemGroup>
<_TempWebConfigToDelete Include="$(BaseIntermediateOutputPath)**\AspnetCompileMerge\**\*" />
</ItemGroup>
<Delete Files="#(_TempWebConfigToDelete)"/>
</Target>
I found several solutions which use Post-Build event.
Is there a way to publish ASP.NET MVC web site with compiled views (to prevent first user view delay) but do not compile them in development environment (to compile site faster)?
Thank you!
P.S. Ideally it would be to configure One Click Publish feature in Visual Studio 2010
Edit
As I understood <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" /> does the same thing as
<MvcBuildViews>true</MvcBuildViews>
<EnableUpdateable>false</EnableUpdateable>
but for early versions
My .csproj looks like
...
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<MvcBuildViews>true</MvcBuildViews>
<EnableUpdateable>false</EnableUpdateable>
...
and views precompile fine but I can't get a single library for deployment like with Asp .net applications. That's why first load page delay still exist...
Please help
You can configure the post-build event to compile views only when you compile in Release mode so that it does not slow you down during development (when you presumably compile in Debug mode.)
For example, the following node in a .csproj will only compile views when the project is compiled in Release mode.
<Target Name="AfterBuild" Condition="'$(Configuration)'=='Release'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
Or you can set MvcBuildViews to true, but only do it for certain configurations:
<MvcBuildViews>true</MvcBuildViews>
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true' And '$(Configuration)'!='Debug'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
Notice i've added And '$(Configuration)'!='Debug'" to the condition.