I have created an event in an AuthenticationService.cs:
public event Action<string?>? LoginChanged;
During the AuthenticationService's Login method, I'm invoking the event:
LoginChanged?.Invoke(username); // This line does get hit when the user logs in, but LoginChanged is null
The event is subscribed to in a BlazorServer component:
UserPartial.razor:
@inject IAuthenticationService AuthenticationService;
...
protected override void OnInitialized()
{
Logger.LogInformation("user.razor initilised 1"); // This does get hit
AuthenticationService.LoginChanged += (string? name) =>
{
Logger.LogInformation("event firing!!!"); // This doesn't get hit
username = name;
StateHasChanged();
};
Logger.LogInformation("user.razor initilised 2"); // This does get hit
base.OnInitialized();
}
The dependency injection for AuthenticationService is set up as a singleton in program.cs:
builder.Services.AddSingleton<IAuthenticationService, AuthenticationService>();
My aim is that when the AuthenticationService's Login method invokes the LoginChanged event, that the event handling code in UserPartial.razor is run.
What seems to be happening is that when LoginChanged?.Invoke(username) is called, the LoginEvent is null, and thus it isn't actually invoking.
I've tried lots of alternative ways of attaching the event handler code, including creating a method in UserPartial.razor like this:
public void LocalLoginChanged(string? name)
{
Logger.LogInformation("event firing!!!");
username = name;
StateHasChanged();
}
And attaching it like this from OnInitialized:
AuthenticationService.LoginChanged += new Action<string?>(LocalLoginChanged);
I've tried other things like calling it from OnInitializedAsync instead of OnInitialized, but everything I try has the same result.
What am I missing? Why is LoginChanged null at the point of invoking it? Clearly I've not set it up correctly, could you point me in the direction of how it should be set up?
I'm using .Net Core 7, Blazor Server.
Ok so I managed to get this working. I didnt pick the same Names, but I think you will get it.
So this is the Code for what would be your Service
public delegate void AuthDelegate(string name);
public interface IEventTesterAuth
{
public event AuthDelegate? OnAuth;
public void FireEvent(string name);
}
public class EventTesterAuth: IEventTesterAuth
{
public event AuthDelegate? OnAuth;
public void FireEvent(string name)
{
OnAuth?.Invoke(name);
}
}
This is the c# code in the Blazor component
private string _someName;
protected override void OnInitialized()
{
EvTeAu.OnAuth += AuthChanged;
base.OnInitialized();
}
public void FireInvoke()
{
EvTeAu.FireEvent("Johnson");
}
private async void AuthChanged(string name)
{
_someName = name;
await InvokeAsync(StateHasChanged);
}
This is the HTML part to test it
<button @onclick="FireInvoke">Invoke</button>
<p role="status">Current name: @_someName</p>
And this is the injection
@inject IEventTesterAuth EvTeAu
And this is the Service adding in the Main method
builder.Services.AddSingleton<IEventTesterAuth, EventTesterAuth>();
Now the main Change i meade was to replace the Action part in your event to delegate since thats how I usually do it. Then i also made sure that your StateHasChanged gets called within a InvokeAsync because without it the Page usually does not Update. You should probably still use an Dispose at some point as recomended by Ale. But for now this does what you want.