I have a project running in .NET Core and I am using VS2017 as IDE.
When I build my project through Visual Studio 2017 it does not automatically add the Views folder and the wwwroot folder to the output in [projectRoot]/bin/Debug/netcoreapp1.1/win10-x64
(BuildDir
). This means that if I try to run my website directly from the .exe file
created in the bin folder, I get an error with the missing views
and wwwroot
. If I manually copy these folders to the BuildDir
then the views load correctly.
This I can setup in my .csproj file with the following:
<Content Update="Views\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
And then the Views
work but now my layout file is not being compiled so I get the following:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - FirstAgenda</title>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css"/>
<link rel="stylesheet" href="~/css/overwrite.css" asp-append-version="true" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/overwrite.css" asp-append-version="true" />
</environment>
</head>
This means that my root folder is not being targeted correctly. And also kinda tells me that just copying the files to the output directory is incorrect.
All of the above is working if I do a publish of my application (also without the addition to the .csproj file). I just have a project runner that I would like to be able to point to the Debug version of my websites executable file, because it is very easy to forget to do a publish compared to just building the project with VS2017.
I just don't know where to go from this and any help will be appreciated?
EDIT:
Added the stripped down version of csproj (which does not work):
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<PreserveCompilationContext>true</PreserveCompilationContext>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.1.0-preview4-final" />
<PackageReference Include="IdentityServer4" Version="1.3.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="1.0.0" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="1.0.0" />
<PackageReference Include="OctoPack" Version="3.5.2" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet">
<Version>1.1.0-preview4-final</Version>
</DotNetCliToolReference>
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools">
<Version>1.0.0-msbuild1-final</Version>
</DotNetCliToolReference>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools">
<Version>1.0.0-msbuild1-final</Version>
</DotNetCliToolReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\[OWNPROJECT]" />
<ProjectReference Include="..\[OWNPROJECT1]" />
</ItemGroup>
</Project>
Also tried creating a new project with dotnet new mvc
And it is also not working.
My dotnet core cli version is [1.0.1].
EDIT:
I followed the steps you outlined. I also tried to create a new project with dotnet new mvc
and followed your steps. Both gave me the same errors. It was unable to find the appsettings.json
. If I then add a propertygroup
to the .csproj. That tells msbuild to copy appsettings.json and web.config to the output
<ItemGroup>
<Content Update="appsettings.json;web.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I can then start the program through the exe, but when I access the index, then when I try to access one of the views it gives me:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[0]
An unhandled exception has occurred while executing the request
System.InvalidOperationException: The view 'Index' was not found. The following locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml
UPDATE:
Shaun Lutins answer seems to be working for me. Both with build and publish options. Only problem was that I was getting an error:
Duplicate 'Content' items were included. The .NET SDK includes 'Content' items from your project directory by default.
But it was resolved by changing the following:
<ItemGroup>
<Content Include="appsettings.json" CopyToOutputDirectory="Always" />
<Content Include="Views\**\*" CopyToOutputDirectory="Always" />
<Content Include="wwwroot\**\*" CopyToOutputDirectory="Always" />
</ItemGroup>
to
<ItemGroup>
<Content Update="appsettings.json;web.config" CopyToOutputDirectory="PreserveNewest"/>
<Content Update="Views\**\*" CopyToOutputDirectory="PreserveNewest" />
<Content Update="wwwroot\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
The challenge as I have interpreted it is to run dotnet build
and be able to execute the compiled EXE from anywhere. The answer requires two steps:
First, modify the csproj to copy required content to the bin. Out of the box, dotnet build
does not copy Views, appsettings.json, or wwwroot to the bin. So, we need to specify CopyToOutputDirectory
explicitly; and to do that, we also need to set EnableDefaultContentItems
to false, otherwise our explicit settings will duplicate the default content item settings.
Second, modify Program.cs to specify the new ContentRoot and WebRoot. Out of the box, Program.cs
sets UseContentRoot(Directory.GetCurrentDirectory())
. Problematically for our situation, the current directory is the directory from which we run the executable. So, if we run the EXE from the command line at our desktop, then the current directory will be C:/Users/MyUser/Desktop
. The app will not find the Views, appsettings.json, and other content.
Here are some working steps that I have used to meet the challenge as I have interpreted it.
cd C:\temp
dotnet new mvc
dotnet restore
dotnet build
cd ..
C:\temp\bin\Debug\netcoreapp1.0\win10-x64\temp.exe
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<OutputType>exe</OutputType>
<EnableDefaultContentItems>false</EnableDefaultContentItems>
</PropertyGroup>
<ItemGroup>
<Content Include="appsettings.json" CopyToOutputDirectory="Always" />
<Content Include="Views\**\*" CopyToOutputDirectory="Always" />
<Content Include="wwwroot\**\*" CopyToOutputDirectory="Always" />
</ItemGroup>
<ItemGroup>
<!-- Package references omitted for clarity -->
</ItemGroup>
</Project>
public class Program
{
public static void Main(string[] args)
{
// C:\temp\bin\Debug\netcoreapp1.0\win10-x64\temp.dll
var assemblyFilePath =
System.Reflection.Assembly.GetEntryAssembly().Location;
// C:\temp\bin\Debug\netcoreapp1.0\win10-x64\
var binDirectory =
System.IO.Path.GetDirectoryName(assemblyFilePath);
Console.WriteLine(assemblyFilePath);
Console.WriteLine(binDirectory);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(binDirectory) // <--
.UseWebRoot("wwwroot") // <--
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With