Reusing Polly Policies with Dependency Injection

Download full source code.

In my previous post “A simple Polly example with WebApi 2” I showed how to make a request to an unreliable endpoint protected by a Polly retry policy. For more on Polly see www.thepollyproject.org.

In that example I created the Polly policy in the constructor of the controller. That of course means it was not reusable, I would have to copy that code into all other controllers that needed the policy, and any policy changes would require me to edit all the controllers. Not a good solution.

In this post I’m going to show how to use dependency injection to share and reuse Polly policies.

Using Dependency Injection with Polly

In this example I’m working with ninject, but you you can use any DI that suits you. See here for more info on ninject – “Web API 2 and ninject, how to make them work together”.

I firstly create all my Polly policies in a simple class like so –

public class Policies
{
    public readonly RetryPolicy<HttpResponseMessage> InternalServerErrorPolicy;
    public readonly RetryPolicy<HttpResponseMessage> RequestTimeoutPolicy;
    public Policies()
    {
        InternalServerErrorPolicy = Policy.HandleResult<HttpResponseMessage>(
           r => r.StatusCode == HttpStatusCode.InternalServerError)
       .WaitAndRetryAsync(3,
           retryAttempt => TimeSpan.FromSeconds(retryAttempt));

        RequestTimeoutPolicy = Policy.HandleResult<HttpResponseMessage>(
            r => r.StatusCode == HttpStatusCode.RequestTimeout)
        .WaitAndRetryAsync(3, 
            retryAttempt => TimeSpan.FromSeconds(Math.Pow(0.2, retryAttempt)));
    }
}

Then my DI class I register the Policies.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<Policies>().ToSelf().InSingletonScope();
}

My controllers take Policies as a constructor parameter, which ninject provides.

public class ItemsController : ApiController
{
    private readonly Policies _policies;
    public ItemsController(Policies policies)
    {
        _policies = policies;
    }
//snip...

The action methods call other controllers wrapped by one of the policies.

HttpResponseMessage httpResponse =
  await _policies.InternalServerErrorPolicy.ExecuteAsync(
     () => httpClient.GetAsync(requestEndpoint));

and

HttpResponseMessage httpResponse = 
  await _policies.RequestTimeoutPolicy.ExecuteAsync(
     () => httpClient.GetAsync(requestEndpoint));

That’s it.

Download full source code.

Web API 2 and ninject, how to make them work together

Full source code to download.

I’ve been using ninject for a few years, but every time I use it with Web Api I hit some problem and they usually stem from not including the right nuget packages, not changing the DependencyResolver or (once) forgetting how to make a binding!

For my future self and your reference, here is how it is done.

1. Nuget packages

Add Ninject.Web.WebApi using nuget to your Web Api project.

That will install two other package dependencies:
Ninject
Ninject.Web.Common

To make everything work you need to add one more nuget package
Ninject.Web.Common.WebHost

This will pull down the WebActivatorEx package and add a new class called NinjectWebCommon to your App_Start directory.

2. Edit NinjectWebCommon.cs

NinjectWebCommon.cs is missing a key feature if you want to use ninject to construct the controllers, and I presume that is why you are using ninject inside a Web Api project.

In the CreateKernel() method add the second line shown below. Now ninject will be used to resolve controller dependencies.

RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

You will need to add a couple of using statements too –

using System.Web.Http;
using Ninject.Web.WebApi;

3. Register some services

To actually register some services we move to the RegisterServices(..) method do some binding.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ICaclulator>().To<Caclulator>();
}

4. Use it all

And here is the usage in the controller.

    public class ValuesController : ApiController
    {
        private readonly ICaclulator _caclulator;
        public ValuesController(ICaclulator calculator)
        {
            _caclulator = calculator;
        }

        public int Get(int num1, int num2)
        {
            return _caclulator.Add(num1, num2);
        }
    }

Full source code to download.