dotnet/aspnetcore

With Blazor .NET 8, using JSHost.ImportAsync in component in a Razor Class Library (RCL) to load a collocated JavaScript module doesn't appear to work

aventius-software opened this issue · 1 comments

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Since the unmarshalled method of calling JavaScript from Blazor has been deprecated I'm trying to use the new JSImport attribute introduced with .NET 7 (although my project is .NET 8) and of course JSHost.ImportAsync to load a collocated JavaScript module, however I cannot get the module to load. The component and the JavaScript file are in a Razor component library (RCL) which I'm referencing in my Blazor webassembly project. I've followed the steps here with some slight modification and this works when the component and JavaScript are in the webassembly project, but if I move them to the RCL then I get an error in the console as show below:-

Unhandled exception rendering component: TypeError: Failed to fetch dynamically imported module: https://localhost:7293/_framework/Test.razor.js

Using normal JS interop from a RCL works fine, it seems that only the JSHost.ImportAsync method doesn't work when called in a RCL

Expected Behavior

After moving the component and code to the RCL, it should work the same as when the component and JavaScript code are in the webassembly project

Steps To Reproduce

  1. Create 'standalone blazor webassembly' app project called 'JSHostImportIssue'
  2. Add a 'razor class library' project to the solution called 'RazorClassLibrary'
  3. Add the following line to the to the 'RazorClassLibrary' project file
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

so that contents now looks like this...

<Project Sdk="Microsoft.NET.Sdk.Razor">

	<PropertyGroup>
		<TargetFramework>net8.0</TargetFramework>
		<Nullable>enable</Nullable>
		<ImplicitUsings>enable</ImplicitUsings>
		<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
	</PropertyGroup>

	<ItemGroup>
		<SupportedPlatform Include="browser" />
	</ItemGroup>

	<ItemGroup>
		<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.5" />
	</ItemGroup>

</Project>
  1. Add dependency reference for the 'RazorClassLibrary' project to the 'JSHostImportIssue' app project
  2. Create empty razor component in 'RazorClassLibrary' project called 'Test.razor' in the root of the project, not in any sub folders
  3. Add following code to the component (taken and amended from https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/import-export-interop?view=aspnetcore-8.0)
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
    (Call JS Example 1)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override async Task OnInitializedAsync()
    {
        await JSHost.ImportAsync("Test", "./Test.razor.js");

        message = GetValueFromJSFunc();
    }
}
  1. Create new cs file called 'Test.razor.cs' in the same location as the 'Test.razor' component
  2. Add following content to the file (taken and amended from https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/import-export-interop?view=aspnetcore-8.0)
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;

namespace RazorClassLibrary;

[SupportedOSPlatform("browser")]
public partial class Test
{
    [JSImport("someFunc", "Test")]
    internal static partial string GetValueFromJSFunc();
}
  1. Create a javascript file called 'Test.razor.js' in the same location as the 'Test.razor' component
  2. Add the following contents to the file
export function someFunc() {
	return "hello from js";
}
  1. Add the following code to the 'Home.razor' component in the main webassembly app project (its under 'Pages' folder)
<RazorClassLibrary.Test />
  1. Run app, the following error occurs listed in the console
Unhandled exception rendering component: TypeError: Failed to fetch dynamically imported module: https://localhost:7293/_framework/Test.razor.js
  1. Also, tried changing the component code to the following (see below), but both produce the same error as above
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
    (Call JS Example 1)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override async Task OnInitializedAsync()
    {        
        await JSHost.ImportAsync("Test", "./_content/RazorClassLibrary/Test.razor.js");

        message = GetValueFromJSFunc();
    }
}
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
    (Call JS Example 1)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override async Task OnInitializedAsync()
    {        
        await JSHost.ImportAsync("Test", "../Test.razor.js");

        message = GetValueFromJSFunc();
    }
}

Exceptions (if any)

No response

.NET Version

8.0.205

Anything else?