I'm working on a Blazor project and I'm trying to move one of the JavaScript files to a class library, I've read the following guides:
- https://learn.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-6.0&tabs=visual-studio#consume-content-from-a-referenced-rcl-1
- https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/?view=aspnetcore-6.0#load-a-script-from-an-external-javascript-file-js
- https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-6.0#javascript-isolation-in-javascript-modules
I'm getting the following error:
I'm not sure what I'm missing or what I need to do to get this to work so here is the setup I have:
Facts:
- I'm using
.NET 6. - I'm using Visual Studio for Mac
Version 17.0 Preview (17.0 build 8754). - The name of the solution is
LinkScreen. - The name of the application project is
Client.Web. - The name of the application assembly is
LinkScreen.Client.Web. - The name of the application default namespace is
LinkScreen.Client.Web. - The hosting model for the application is Web Assembly.
- The name of the class library project is
Client.BrowserInterop. - The name of the class library assembly is
LinkScreen.Client.BrowserInterop. - The name of the class library default namespace is
LinkScreen.Client.BrowserInterop.
Project Structur and Code
- Inside the class library I have a script file called
screen-capture.jsunder the following directorywwwroot\scriptslike so:
The build action for this is set to Content and copy to output directory is set to Do not copy.
- The class library is referenced to the application like so:
- I have a C# class called
ScreenCapturethat wraps the JavaScript module that is thescreen-capture.jsand retuns a reference like so:
public static async ValueTask<ScreenCapture> CreateAsync(
IJSRuntime jsRuntime,
ElementReference videoTagReference)
{
var jsModuleRef = await jsRuntime.InvokeAsync<IJSInProcessObjectReference>("import", "./_content/LinkScreen.Client.BrowserInterop/screen-capture.js").ConfigureAwait(false);
return new ScreenCapture(jsModuleRef, videoTagReference);
}
Previously I had a reference to the screen-capture.js inside index.html like so <script src="_content/LinkScreen.Client.BrowserInterop/scripts/screen-capture.js" type="module"></script> because I thought it was required to use the IJSRuntime methods and then someone on the Blazor channel enlighten me so I removed the reference but I'm still getting the same 404 error now from the wrapper by calling jsRuntime.InvokeAsync.
It's important to note that everything works correctly when the script is inside the wwwroot/scripts of application folder.
- My program.cs file is the default for .NET 6 Blazor WebAssembly projects and is like so:
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using LinkScreen.Client.Web;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
Things I've tried and it still doesn't work:
- Clean the project, delete the bin and obj directories.
- Clear the browser's cache as well as disabling it.
- I've tried both Safari and Chrome but I get the exact same issue.





<script src="./_content/Client.BrowserInterop/scripts/screen-capture.js />. Browsers have trouble with modules and I bet your own interop code is calling the functions directly, not trying to import any modules.script type="import"you were importing the JS file into the script tag, not the global namespace. In your current code you're loading the file stored atwwwroot/screen-capture.js. You need to use./_content/LinkScreen.Client.BrowserInterop/scripts/screen-capture.jsinstead. The path"./_content/Client.BrowserInterop/ScreenCapture.razor.js"in my question works because the isolated JS file is stored in the same folder as the component at the project root. The compiler uses "magic" to make the JS file appear in the./_content/Client.BrowserInterop/path