Aspnetcore: Unable to create Blazor app with fsproj

Created on 19 Sep 2018  路  14Comments  路  Source: dotnet/aspnetcore

I've attempted to create an all-F# Blazor app with each release, but it seems that the current solution requires a csproj and expects all files to be C#. I suspect this is because the Blazor tooling is inspecting the solution to find .cshtml files and generate the .g.cs files the compiler will use. I've built a F# renderer, Trail, that doesn't require this step, and I would love to build Blazor apps with just the fsproj. The only thing in the csproj in my Trail sample apps is the call to build and run the host builder.

I think this should be possible as the mono wasm tooling appears able to run F# projects. I would be very glad to help out with investigating whether this is possible and desirable from a Blazor project perspective.

area-blazor

Most helpful comment

Fixed for the 0.6 release

All 14 comments

I've attempted to create an all-F# Blazor app with each release, but it seems that the current solution requires a csproj and expects all files to be C#.

@panesofglass Can you walk me through the steps you are trying and describe what specifically doesn't work?

I think this should be possible as the mono wasm tooling appears able to generate wasm from F# projects

I believe that's unrelated. Blazor doesn't generate any WebAssembly files currently (although an AoT compilation story to WebAssembly is something we're investigating with the mono team). The WebAssembly for the .NET runtime is prebuilt and packaged with the Blazor framework. Blazor projects are built to normal .NET assemblies, which presumably an F# Blazor project would do as well.

I'm not sure exactly what you're asking for help with, but .cshtml files require a .csproj and that will be the case for the foreseeable future.

Blazor generates C# files during the build, and those files are compiled into an assembly with other C# files in the same project. If you're trying to create an all F# Blazor app, you'll need to forego .cshtml entirely, or put in a project that you reference from F#.

@danroth27 yes, I'll create a branch in https://github.com/panesofglass/trail soon that will show what I've tried so far.

@rynowak I am not using .cshtml but generating the target render tree from F#, e.g.

[<LayoutAttribute(typeof<MainLayout>)>]
[<RouteAttribute("/")>]
type Index () =
    inherit Trail.Component()

    override __.Render() =
        Dom.Fragment [
            Dom.h1 [] [ Dom.text "Hello, world!" ]
            Dom.text "\n\nWelcome to your new app.\n\n"
            Dom.comp<SurveyPrompt> [Dom.HtmlAttribute("title", "How is Blazor working for you?")] []
        ]

Ok, so if there's a specific problem that we can help - could you provide more information?

@rynowak here's a branch with an all-fsharp sample. With <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.5.1" /> in the .fsproj, I get a load of output that appears to be C# syntax checking:

C:\Code\trail\src\Trail\obj\Debug\netstandard2.0\Trail.AssemblyInfo.fs(15,69): warning FS2003: The attribute System.Reflection.AssemblyInformationalVersionAttribute specified version '0.0.7+d163d88da1072a287b177cccb2c55cf59a33478f', but
this value is invalid and has been ignored [C:\Code\trail\src\Trail\Trail.fsproj]
Counter.fs(1,27): error CS1514: { expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
App.fs(1,21): error CS1514: { expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Startup.fs(1,21): error CS1514: { expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Shared.fs(1,28): error CS1514: { expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Program.fs(1,15): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
FetchData.fs(1,27): error CS1514: { expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
App.fs(4,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Counter.fs(4,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
App.fs(5,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Counter.fs(5,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Startup.fs(4,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Shared.fs(4,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
App.fs(6,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Startup.fs(5,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
FetchData.fs(4,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Counter.fs(6,6): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
...
Shared.fs(114,69): error CS1513: } expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Shared.fs(114,74): error CS1002: ; expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
Shared.fs(114,74): error CS1513: } expected [C:\Code\trail\sample\all-fsharp\BlazorFSharp\BlazorFSharp.fsproj]
    0 Warning(s)
    623 Error(s)

If I take that reference out, I can build successfully, but the app fails to run:

Application startup exception: System.IO.FileNotFoundException: Could not find file 'C:\Code\trail\sample\all-fsharp\BlazorFSharp\bin\Debug\netstandard2.0\BlazorFSharp.blazor.config'.
File name: 'C:\Code\trail\sample\all-fsharp\BlazorFSharp\bin\Debug\netstandard2.0\BlazorFSharp.blazor.config'
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
   at System.IO.StreamReader..ctor(String path, Encoding encoding)
   at System.IO.File.ReadLines(String path)
   at Microsoft.AspNetCore.Blazor.Server.BlazorConfig..ctor(String assemblyPath)
   at Microsoft.AspNetCore.Builder.BlazorApplicationBuilderExtensions.UseBlazor(IApplicationBuilder app, BlazorOptions options)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
crit: Microsoft.AspNetCore.Hosting.Internal.WebHost[6]
      Application startup exception
System.IO.FileNotFoundException: Could not find file 'C:\Code\trail\sample\all-fsharp\BlazorFSharp\bin\Debug\netstandard2.0\BlazorFSharp.blazor.config'.
File name: 'C:\Code\trail\sample\all-fsharp\BlazorFSharp\bin\Debug\netstandard2.0\BlazorFSharp.blazor.config'
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
   at System.IO.StreamReader..ctor(String path, Encoding encoding)
   at System.IO.File.ReadLines(String path)
   at Microsoft.AspNetCore.Blazor.Server.BlazorConfig..ctor(String assemblyPath)
   at Microsoft.AspNetCore.Builder.BlazorApplicationBuilderExtensions.UseBlazor(IApplicationBuilder app, BlazorOptions options)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

Unhandled Exception: System.IO.FileNotFoundException: Could not find file 'C:\Code\trail\sample\all-fsharp\BlazorFSharp\bin\Debug\netstandard2.0\BlazorFSharp.blazor.config'.
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
   at System.IO.StreamReader..ctor(String path, Encoding encoding)
   at System.IO.File.ReadLines(String path)
   at Microsoft.AspNetCore.Blazor.Server.BlazorConfig..ctor(String assemblyPath)
   at Microsoft.AspNetCore.Builder.BlazorApplicationBuilderExtensions.UseBlazor(IApplicationBuilder app, BlazorOptions options)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.StartAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
   at Microsoft.AspNetCore.Blazor.Cli.Program.Main(String[] args)

You can find a working, csproj + fsproj sample here.

It seems without the Microsoft.AspNetCore.Blazor.Build reference, the *.blazor.config, dist folder, etc. are not generated. However, that reference appears to expect a .csproj and C# files.

Alright thanks, I'll take a look at this and see what the problem is.

So the issue here is that the _BlazorTempCompile task is indeed compiling all of your .fs files using CSC.

The fix for this is to skip the two-phase compile when the project is not C#. PR coming shortly.

Fixed for the 0.6 release

Thank you, @rynowak!

I just want to add that I am delighted you took the time to investigate and resolve this issue. Thank you very much!

Thanks!

If you want to experiment with this locally, you can hack your RazorCompilation.targets to improve this check https://github.com/aspnet/Blazor/commit/5df4eef30497bf13217312b250b247bc83994a9e

If you run into any other issues let us know.

This works great! Thanks again, @rynowak!

Was this page helpful?
0 / 5 - 0 ratings