I am trying to call a .net method from some JavaScript in my Blazer server application, following this documentation but I always get No call dispatcher has been set
.
I want to have the .net methods in a service that is always there, NOT a component (I find the Blazer components always seem to dispose of themselves). For example, I will use it for logging.
I have declared this (everything static)….
namespace MyNamespace.Utility
{
public static class JsHelperService
{
static JsHelperService()
{
var i = 0; // just for testing with breakpoint
}
// Call from program.cs to make sure class is instantiated
public static void Init()
{
}
[JSInvokable("WriteInfo")]
public static void WriteInfo(string message)
{
Logger.Instance.WriteInfo(message);
}
}
}
Then in JavaScript
I have
function setupLogging() {
debugger; // just while debugging
window.dotnetLogger = window.dotnetLogger || {};
window.dotnetLogger.writeInfo = function (message) {
window.DotNet.invokeMethodAsync('MyNamespace.JsHelperService', 'WriteInfo');
};
}
I then call setupLogging()
to set this up.
When I debug, all seems to be there, ie window.DotNet
is available etc.
However, when I then call window.dotnetLogger.writeInfo
from elsewhere in JavaScript, I can see the function is called, but as soon as it executes the
window.DotNet.invokeMethodAsync
I get the error
Uncaught Error: No call dispatcher has been set.
at v (blazor.web.js:1:1776)
at e.invokeMethodAsync (blazor.web.js:1:2231)
at window.dotnetLogger.writeInfo (site.js:41:18)
I was not sure what to use for the namespace, we the doco does not even have an example, so I tried both MyNamespace.JsHelperService
and just MyNamespace
but neither made a difference.
Would anyone know how I can fix this?
3
Here is my working sample.
JsHelperService.cs
using Microsoft.JSInterop;
namespace BlazorApp1.Utility
{
public static class JsHelperService
{
public static void Init()
{
}
[JSInvokable("WriteInfo")]
public static void WriteInfo(string message)
{
Console.WriteLine($"[Info]: {message}");
}
}
}
Register it
var app = builder.Build();
// Register it.
JsHelperService.Init();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
Counter.razor
@page "/counter"
@inject IJSRuntime JSRuntime
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("setupLogging");
await JSRuntime.InvokeVoidAsync("window.dotnetLogger.writeInfo", "this is test message.");
}
}
private void IncrementCount()
{
currentCount++;
}
}
site.js
document.addEventListener('blazor:loaded', function () {
setupLogging();
});
function setupLogging() {
window.dotnetLogger = window.dotnetLogger || {};
window.dotnetLogger.writeInfo = function (message) {
window.DotNet.invokeMethodAsync('BlazorApp1', 'WriteInfo', message);
};
}
Test Result
3