Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple times the event is called #7

Open
hsvasan opened this issue Jun 30, 2021 · 7 comments
Open

Multiple times the event is called #7

hsvasan opened this issue Jun 30, 2021 · 7 comments

Comments

@hsvasan
Copy link

hsvasan commented Jun 30, 2021

I am using the BlazorServer side project. i have created a HttpInterfaceService and created the AfterSendAsync and also removed the same in the disposeevent.
This is working fine, but it is called more than 5 times for every exception is being called.
Advise any settings to be done by me or is it an existing bug in the package.

@jsakamoto
Copy link
Owner

@hsvasan Could you attach all files of a sample project which can reproduce that issue as a single zip package to this thread?

@scottkuhl
Copy link

I was seeing the same thing on BeforeSendAsync. The issue was I injected a custom http interceptor at the component level. So, it was registering an event listener for every component on the page that had this injected. Then each registered instance of the interceptor would fire once for every HTTP request in total on the page.

@jsakamoto This may be what @hsvasan was also doing.

I solved it by registering the http interceptor once in the App.razor component.

public partial class App : IDisposable
{
    [Inject] protected HttpInterceptor Interceptor { get; set; } = default!;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            Interceptor.DisposeEvent();
        }
    }

    protected override void OnInitialized()
    {
        Interceptor.RegisterAfterSendEvent();
        Interceptor.RegisterBeforeSendEvent();
    }
}

Custom interceptor:

public class HttpInterceptor
{
    private readonly IAuthenticationService _identityService;
    private readonly HttpClientInterceptor _interceptor;
    private readonly ISnackbar _snackbar;

    public HttpInterceptor(IAuthenticationService identityService, HttpClientInterceptor interceptor, ISnackbar snackbar)
    {
        _identityService = identityService;
        _interceptor = interceptor;
        _snackbar = snackbar;
    }

    public void DisposeEvent()
    {
        _interceptor.AfterSend -= AfterSend;
        _interceptor.BeforeSendAsync -= BeforeSendAsync;
    }

    public void RegisterAfterSendEvent()
    {
        _interceptor.AfterSend += AfterSend;
    }

    public void RegisterBeforeSendAsyncEvent()
    {
        _interceptor.BeforeSendAsync += BeforeSendAsync;
    }

    private void AfterSend(object? sender, HttpClientInterceptorEventArgs e)
    {
        HttpHandler.HandleResponse(_snackbar, e);
    }

    private async Task BeforeSendAsync(object sender, HttpClientInterceptorEventArgs e)
    {
        var request = e.Request;
        if (request != null)
        {
            await _identityService.TokenInterceptorAsync(request);
        }
    }
}

@jsakamoto
Copy link
Owner

@scottkuhl Thank you for providing important information and feedback!
I'll look into your code well later.

@scottkuhl
Copy link

@jsakamoto I was speaking with another developer, and this did not solve the issue for them because they had multiple components on the page making HTTP requests. That does not mean there is anything wrong with HttpClientInterceptor, this is just more of an FYI if you want to investigate extending the code base to support this scenario more easily by optionally only firing once per page request.

@jsakamoto
Copy link
Owner

@scottkuhl Ok, I got it. Again, thank you for your kindness and for providing such helpful information. 👍

@scottkuhl
Copy link

@drajatisme I don't have the exact code on how he did it, but he created a boolean variable per page request that flipped on the first hit and then would not fire on subsequent hits by checking the state of the flag.

@jsakamoto
Copy link
Owner

jsakamoto commented Nov 27, 2022

Uh... hi there, are you using this library on Blazor Server app, not on Blazor WebAssembly apps?
I designed this library for only Blazor WebAssembly apps. (You can see the README of this library says the title of this library is "Blazor WebAssembly (client-side) HttpClient Interceptor".)
So I have not cared about the lifetimes of the services provided by this library. Therefore, the lifetimes of the services provided by this library is singleton!

See also: https://github.com/jsakamoto/Toolbelt.Blazor.HttpClientInterceptor/blob/master/Toolbelt.Blazor.HttpClientInterceptor/HttpClientInterceptorExtension.cs#L23

That is why the event is called multiple times on Blazor Server apps, isn't it?

Now, I'm considering changing the lifetimes of the services from "singleton" to "scoped" to support Blazor Server app scenarios.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants