Yes, there are loads of questions and answers on this but I can't find one that works for me - I just can't see what I'm missing, or doing wrong.
Windows desktop app that just needs to serve a couple of Razor pages (along with SignalR). If I browse to https://localhost:5000 with V1 of the HomeController (see below) then the browser correctly displays the string, so I know I'm browsing to the correct URI. But if I change the controller to return the view instead, I get the following:
An unhandled exception occurred while processing the request.
InvalidOperationException: The view 'Index' was not found. The following locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml
/Pages/Shared/Index.cshtml
Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful(IEnumerable<string> originalLocations)
When running the latter, the output window displays:
Microsoft.Hosting.Lifetime: Information: Now listening on: http://localhost:5000
Microsoft.Hosting.Lifetime: Information: Application started. Press Ctrl+C to shut down.
Microsoft.Hosting.Lifetime: Information: Hosting environment: Development
Microsoft.Hosting.Lifetime: Information: Content root path: C:\Users\geoff\source\repos\xxx\yyy\bin\Debug\netcoreapp3.0
Index.cshtml (in that casing) is located at (also under wwwroot\Views etc):
C:\Users\geoff\source\repos\xxx\yyy\bin\Debug\netcoreapp3.0\Views\Home\Index.cshtml
Index.cshtml is set to BuildAction: Content and CopyToOutput: CopyIfNewer, and yes, the file is there when running with the correct casing.
I have read something about adding a view engine but my understanding is the Razor one is there anyway. I think that's the only thing I haven't tried. I also tried custom routes instead of the default, with no success.
Help greatly appreciated.
Part of .csproj:
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWPF>true</UseWPF>
<PreserveCompilationContext />
<MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
<MvcRazorExcludeViewFilesFromPublish>false</MvcRazorExcludeViewFilesFromPublish>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>
<ItemGroup>
<None Remove="Views\Home\Index.cshtml" />
<None Remove="wwwroot\Views\Home\Index.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Home\Index.cshtml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="wwwroot\Views\Home\Index.cshtml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="1.1.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="wwwroot\**\*;**.cshtml">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AvalonEdit" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="3.0.0-preview3-19153-02" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.0.0-preview5-19227-01" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.2.0" />
</ItemGroup>
</Project>
App.xaml.cs:
public partial class App : Application
{
private IHost _host;
protected override void OnStartup(StartupEventArgs e)
{
string path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
_host = Host.CreateDefaultBuilder(e.Args)
.UseContentRoot(path)
.ConfigureWebHostDefaults(webHostBuilder => webHostBuilder.UseStartup<StartUp>())
.ConfigureServices(services =>
{
services.AddTransient<MainWindow>();
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
services.AddMvc();
services.AddSignalR().AddHubOptions<SsoHub>(options =>
{
options.EnableDetailedErrors = true;
});
services.AddSingleton<ISsoHubHelper, SsoHubHelper>();
})
.Build();
_host.Start();
}
protected override void OnExit(ExitEventArgs e) => _host.Dispose();
}
Part of startup.cs:
public class StartUp
{
public static IServiceProvider ServiceProvider { get; private set; }
public static T GetService<T>() { return ServiceProvider.GetRequiredService<T>(); }
public static ISsoHubHelper HubContext;
public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
app.UseCors(builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
app.UseStaticFiles();
app.UseStatusCodePages();
app.UseDeveloperExceptionPage();
app.UseMvcWithDefaultRoute();
app.UseSignalR((configure) =>
{
var desiredTransports =
HttpTransportType.WebSockets |
HttpTransportType.LongPolling;
configure.MapHub<SsoHub>("/ssohub", (options) =>
{
options.Transports = desiredTransports;
});
});
ServiceProvider = serviceProvider;
HubContext = GetService<ISsoHubHelper>();
}
}
HomeController.cs (V1 - works):
public class HomeController : Controller
{
public string Index()
{
return "Hello, world!";
}
}
HomeController.cs (V2 - index.cshtml not found):
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}