Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject Service Fabric service context into asp.net core middleware?

I have a Service Fabric asp.net core stateless service which implements custom middleware. In that middleware I need access to my service instance. How would I go about injecting this using asp.net core's built-in DI/IoC system?

public class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext httpContext)
    {
        // ** need access to service instance here **
        return _next(httpContext);
    }
}

Someone mentioned accomplishing this using TinyIoC in Web Api 2 in the Apr 20, 2017 Q&A #11 [45:30] with the Service Fabric team. As well that the current recommended method is to use asp.net core.

Any help or examples would be greatly appreciated!

like image 669
rktect Avatar asked Dec 07 '25 15:12

rktect


2 Answers

In the asp.net core stateless service that creates the ServiceInstanceListener you can inject the context like this:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new[]
        {
            new ServiceInstanceListener(serviceContext =>
                new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                {
                    logger.LogStatelessServiceStartedListening<WebApi>(url);

                    return new WebHostBuilder().UseWebListener()
                                .ConfigureServices(
                                    services => services
                                        .AddSingleton(serviceContext) // HERE IT GOES!
                                        .AddSingleton(logger)
                                        .AddTransient<IServiceRemoting, ServiceRemoting>())
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                .UseStartup<Startup>()
                                .UseUrls(url)
                                .Build();
                }))
        };
    }

Your middleware than can use it like this:

public class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext httpContext, StatelessServiceContext serviceContext)
    {
        // ** need access to service instance here **
        return _next(httpContext);
    }
}

For a complete example take a look at this repository: https://github.com/DeHeerSoftware/Azure-Service-Fabric-Logging-And-Monitoring

Points of interest for you:

  • Setting up the DI: https://github.com/DeHeerSoftware/Azure-Service-Fabric-Logging-And-Monitoring/blob/master/src/WebApi/WebApi.cs
  • Using context in middleware: https://github.com/DeHeerSoftware/Azure-Service-Fabric-Logging-And-Monitoring/blob/master/src/ServiceFabric.Logging/Middleware/RequestTrackingMiddleware.cs
like image 93
Peter Bons Avatar answered Dec 09 '25 16:12

Peter Bons


Dependency injection via constructor works for middleware classes as well as for others. Just add additional parameters to the middleware constructor

public MyMiddleware(RequestDelegate next, IMyService myService)
{
    _next = next;
    ... 
}

But also you can add dependency directly to the Invoke method

Documentation: Because middleware is constructed at app startup, not per-request, scoped lifetime services used by middleware constructors are not shared with other dependency-injected types during each request. If you must share a scoped service between your middleware and other types, add these services to the Invoke method's signature. The Invoke method can accept additional parameters that are populated by dependency injection.

public class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
    {
        svc.MyProperty = 1000;
        await _next(httpContext);
    }
}
like image 41
Set Avatar answered Dec 09 '25 16:12

Set



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!