2

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();
    }

}
GeoffM
  • 1,603
  • 5
  • 22
  • 34
  • Have you created the view Index for the home controller? replace return view in v 2 with return new EmptyResult(); if it works then for sure you did not created the index view for that particular controller – Claudio Corchez Jun 06 '19 at 18:59
  • I'm not sure whether you mean "the view called Index[.cshtml]" or "the view-index". The file Index.cshtml is in the correct place. I tried EmptyResult() and a blank page appeared (92 B, status 200). – GeoffM Jun 06 '19 at 19:10
  • if it loaded a blank page with return empty result I am sure you don t have an index page for the HomeController. You should have the view like this , the same exact name and also in the same exact folder https://ibb.co/6D8hkRT – Claudio Corchez Jun 06 '19 at 19:16
  • I can't see anything wrong - the file is there: https://ibb.co/72mx3bW – GeoffM Jun 06 '19 at 20:28
  • I just saw that in App.xaml.cs you have a different content root. Try to put .UseContentRoot(Directory.GetCurrentDirectory()) and see if it works. Or debug the path variable and check if is pointing to the correct path. – Claudio Corchez Jun 06 '19 at 22:37
  • Directory.GetCurrentDirectory() and System.Reflection.Assembly.GetEntryAssembly().Location return the same value in this instance. – GeoffM Jun 06 '19 at 22:57

1 Answers1

3

Found it. Sigh. Through a fairly unrelated Q&A, I used resource monitor to determine that no file opens were even being attempted. That led me to believe the pages should have been compiled - and that led to this post which indicated a breaking change. To quote from one of the answers (credit: Dmitry Pavlov):

  1. Reference Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation (prerelease)
  2. Call services.AddMvc().AddRazorRuntimeCompilation()

And finally it works. The cshtml file was there all along, as it should have been and knew it was, but it just wasn't getting compiled.

GeoffM
  • 1,603
  • 5
  • 22
  • 34