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

Scoped service bug #1133

Closed
Assassinbeast opened this issue Oct 19, 2022 · 3 comments
Closed

Scoped service bug #1133

Assassinbeast opened this issue Oct 19, 2022 · 3 comments

Comments

@Assassinbeast
Copy link

Assassinbeast commented Oct 19, 2022

I have Scoped lifetime problem with Isolated runtime.

It looks like there are two scoped lifetimes for one http request.
One for the "Middlewares" and one for the "Function".

Here is my code:

Startup.cs

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults((IFunctionsWorkerApplicationBuilder configure) =>
    {
        configure.UseMiddleware<MyMiddleware>();
        configure.UseMiddleware<MyMiddleware2>();
    })
    .ConfigureServices(services =>
    {
        services.AddScoped<FooService>();
        services.AddScoped<BarService>();
    })
    .Build();
host.Run();

Function1.cs

namespace FunctionApp1
{
    public class Function1
    {
        private readonly FooService _fooService;
        private readonly BarService _barService;

        public Function1(FooService fooService, BarService barService)
        {
            _fooService = fooService;
            _barService = barService;
        }

        [Function("Function1")]
        public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
        {
            _fooService.LogFooId();
            _barService.Start();
            return req.CreateResponse(HttpStatusCode.OK);
        }
    }

    public class MyMiddleware : IFunctionsWorkerMiddleware
    {
        private readonly FooService _fooService;

        public MyMiddleware(FooService fooService)
        {
            _fooService = fooService;
        }

        public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
        {
            _fooService.LogFooId();
            await next(context);
        }
    }
    public class MyMiddleware2 : IFunctionsWorkerMiddleware
    {
        private readonly FooService _fooService;

        public MyMiddleware2(FooService fooService)
        {
            _fooService = fooService;
        }

        public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
        {
            _fooService.LogFooId();
            await next(context);
        }
    }

    public class FooService
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        private readonly ILogger _logger;

        public FooService(ILogger<FooService> logger) 
        {
            _logger = logger;
        }

        public void LogFooId()
        {
            _logger.LogInformation($"FooId: {Id}");
        }
    }

    public class BarService
    {
        private readonly FooService _fooService;

        public BarService(FooService fooService)
        {
            _fooService = fooService;
        }

        public void Start()
        {
            _fooService.LogFooId();
        }
    }
}

When i call "http://localhost:7071/api/Function1", then it will log this out:

FooId: 2514bc34-f5d6-4833-b14b-5090020479f5
FooId: 2514bc34-f5d6-4833-b14b-5090020479f5
FooId: 3e1a5a61-c90c-4e67-bfc6-3c3151933c34
FooId: 3e1a5a61-c90c-4e67-bfc6-3c3151933c34

Its expected that there should be 1 scoped lifetime in one http request, where the "Middleware" and "Function" scopes are both shared.

So this is a bug, correct?

Im using:

Core Tools Version: 4.0.4829 Commit hash: N/A (64-bit)
Function Runtime Version: 4.11.2.19273

It happens both with .NET 7 rc 2 and .NET 6 with the latest versions of the nuget packages and also the preview packages.

Workaround

My workout right now, is to instantiate all services in my middleware through the FunctionContext, and then it will work

public class MyMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var fooService = context.InstanceServices.GetRequiredService<FooService>();
        fooService.LogFooId();
        await next(context);
    }
}
public class MyMiddleware2 : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var fooService = context.InstanceServices.GetRequiredService<FooService>();
        fooService.LogFooId();
        await next(context);
    }
}

Then when i call the api, it will log out:

FooId: 7b36df46-8ec2-41c8-97f7-57a642ac743f
FooId: 7b36df46-8ec2-41c8-97f7-57a642ac743f
FooId: 7b36df46-8ec2-41c8-97f7-57a642ac743f
FooId: 7b36df46-8ec2-41c8-97f7-57a642ac743f
@kshyju
Copy link
Member

kshyju commented Oct 19, 2022

Dupe of #811

@kshyju
Copy link
Member

kshyju commented Oct 21, 2022

@Assassinbeast Please take a look at the dupe linked above. Let us know if you still have questions. Thanks!

@ghost
Copy link

ghost commented Oct 25, 2022

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

@ghost ghost closed this as completed Oct 28, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Nov 27, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants