Letting a request fail with Polly

Polly is fantastic for transparently retrying a request but there is always a point at which you must give up. Here you have a choice, let the request fail and inform the original caller or use the Fallback feature of Polly. In this post I’m going to show how to let the request fail. I’ll post another time on the Polly Fallback feature.

With Polly, failing is done in much the same was as you would do without Polly. Make the request, examine the response, return the appropriate status to the caller.

The example code below shows this when calling a Web Api 2 endpoint. The hoped for response is Ok (200), any other is considered a failure.

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

if (httpResponse.IsSuccessStatusCode)
{
    int number = await httpResponse.Content.ReadAsAsync<int>();
    return Ok(number);
}

string errorMessage = await httpResponse.Content.ReadAsStringAsync();
return Content(httpResponse.StatusCode, errorMessage);

Fallback would all me to return some default number and OK even if the web request failed. Coming soon…

How to install .NET Framework 4.7 in Visual Studio 2017

Microsoft just released .NET Framework 4.7, but surprisingly it is not the easiest to install.

Here are the steps for Windows 10, as of this writing, it is not available for earlier versions for of Windows.

1. Install Windows 10 Creators Update

Go here https://www.microsoft.com/en-us/software-download/windows10, download and install. This will take a while and will reboot your computer a few times.

2. Install Visual Studio 2017 Updates

In Visual Studio, go to Tools -> Extensions and Updates, install any available updates.

(You might have the option here to install 4.7, see the image below in step 4.)

3. Open Visual Studio 2017 Installer

Use the Start Menu to search for the Visual Studio Installer.

In the installer, click Modify on the version of Visual Studio you have installed.

4. Install .NET framework 4.7

Click .NET desktop development.

On the right select .NET Framework 4.7 and finally install.

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.

A simple Polly example with WebApi 2

Download full source code.

If you are calling APIs and you haven’t heard about The Polly Project, you should check it out. It helps take care of many common problems like unreliable connections, retries and circuit breaking. It can also be used to wrap code where other forms of transient exception may occur.

In this blog post I’m going to show the wait and retry policy when calling an unreliable Web Api endpoint.

When using Polly there are two pieces that need you need to code – the policy and the execution of code wrapped by the policy.

In this example the policy is created in the constructor of the controller, this is NOT what you should do in a real application. For an example using DI to share policies see “Reusing Polly Policies with Dependency Injection”.

readonly RetryPolicy<HttpResponseMessage> _httpRequestPolicy;

public ValuesController()
{
    _httpRequestPolicy = Policy.HandleResult<HttpResponseMessage>(
            r => r.StatusCode == HttpStatusCode.InternalServerError)
        .WaitAndRetryAsync(3,
            retryAttempt => TimeSpan.FromSeconds(retryAttempt));
}

This policy states that in the event that a HttpResponseMessage has a of InternalServerError, the request should be tried up to three times with a back off increasing by one second each time.

That’s the policy in place, now we need to call the web service endpoint.

public async Task<IHttpActionResult> Get()
{
   var httpClient = GetHttpClient();
   string requestEndpoint = "numbers/Get"; // numbers is the name of the controller being called

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

   IEnumerable<int> numbers = await httpResponse.Content.ReadAsAsync<IEnumerable<int>>();
   
   return Ok(numbers);
}

If you execute the code it makes a GET request to http://localhost:2351/api/values, despite two failures when calling the NumbersController you will get a 200 response and a list of numbers.

If you want to verify this, step through the provided solution with the debugger. You’ll see that the first two requests to the NumbersContoller return 500 errors and that the third succeeds and returns an array of ints.

With just a few lines of code Polly provided us with a robust wait and retry mechanism for web requests.

In another blog I’ll show a better way of defining policies so they can be used in any controller.

Download full source code.

Web Api 2 Without MVC

Download full source code.

When building a Web Api 2 application there is much unneeded MVC baggage that comes along with it.

To start with all the css, html and javascript can go, then most of the packages, most of referenced dlls and almost all the C#.

Here are side by side comparisons of what you get and what you need.

All you really need for Web Api 2 is is the Global.asax to call WebApiConfig.Register which sets up the default routes and then a controller to perform an action.

Global.asax

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }
}

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

ValuesController.cs

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] {$"Guid 1: {Guid.NewGuid()}", $"Guid 2: {Guid.NewGuid()}" };
    }
}

Web API 2 Controller with multiple GET methods – part 2

I have two other posts on multiple GET methods, one for ASP.NET 5 Web Api, and another for Web Api 2.

Download full source code.

A few months ago I wrote a post explaining how to create a controller with multiple GET methods.
In that I used the combination of [RoutePrefix..] and [Route...] to generate routes like

  • http://…/api/values/geta
  • http://…/api/values/getb

Attribute parameter names and type

In this post I will show a different way of achieving multiple GETs by matching the type of parameter passed to the controller with the appropriate method.

In the first example I will match a method to an int being passed in, note the [Route("{id:int}")], this specifies that the expected parameter is named “id” and is an int.

// GET api/values/7
[Route("{id:int}")]
public string Get(int id)
{
    return $"You entered an int - {id}";
}

It is no problem to add another GET method with a [Route("{id:Guid}")]. This works fine because there is no way and int and Guid can be confused.

// GET api/values/AAC1FB7B-978B-4C39-A90D-271A031BFE5D
[Route("{id:Guid}")]
public string Get(Guid id)
{
    return $"You entered a GUID - {id}";
}

Where we start having problems is when the attribute routing system can’t determine which method you were attempting to call because it can’t distinguish an int from a long (or a string, decimal etc.)

For example, if we had another GET method taking a long, it would cause many runtime errors.

// GET api/values/8 - this will not work because it could be an int or a long
// GET api/values/4147483647 - this works because it can ONLY be a long
[Route("{id:long}")]
public string Get(long id)
{
    return $"You entered an long - {id}";
}

If we called http://...api/values/8, the attribute routing system has no way of knowing whether the GET method for the int or the long should be called.

But if we called http://...api/values/4147483647, that number is larger than an int can hold, the attribute routing system knows only one method matches the call.

If you want to have longs and ints in the same controller one of the routes needs to be altered. Note the new route – [Route("large/{id:long}")].

To call it now use http://...api/values/large/8 or http://...api/values/large/4147483647

[Route("large/{id:long}")]
public string Get(long id)
{
    return $"You entered an long - {id}";
}

Download full source code.

Downloading an in-memory file using Web Api 2

Download full source code

At first you think it’s going to be easy to download a file from Web Api, but as I discovered, it was not.

In my case I wanted to load data from the database, perform some processing and return a subset of the data as a file. This meant I needed to send something that was in memory back to the caller as a file; I was NOT loading a file from the disk.

For simplicity I will skip all the database work and processing and jump to the in-memory object and how to return that.

The code is fairly self explanatory.

using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Web.Http;
using System.Web.Http.Results;

namespace WebApi2DownloadInMemoryFile.Controllers
{
    public class FileDownloadController : ApiController
    {
        public IHttpActionResult Get()
        {
            string someTextToSendAsAFile = "Hello world";
            byte[] textAsBytes = Encoding.Unicode.GetBytes(someTextToSendAsAFile);

            MemoryStream stream = new MemoryStream(textAsBytes);

            HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StreamContent(stream)
            };
            httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "WebApi2GeneratedFile.txt"
            };
            httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

            ResponseMessageResult responseMessageResult = ResponseMessage(httpResponseMessage);
            return responseMessageResult;
        }
    }
}

Download full source code

Fluent Validation with Web Api 2

Full source code here.

I wrote blog post in 2015 on using the Fluent Validation NuGet package for complex validation needs. In the post the validator checked that a create person request had at least one active primary phone and at least one active primary email. Using Fluent Validation this was easy.

The blog post used a simple console application, but I now realize that a lot of people are having difficulty using this in Web API, especially when they have to consume the response from Web Api and look for potential errors from the Fluent Validation package.

I see an approach put forward Matthew Jones, but I don’t like the response rewriting. If you are making a request to a Web Api for a Person, you are no longer getting a Person, you’re getting a ResponsePackage with Person as an object inside. It causes problems with testing – calling the action method directly from a test return a different object then when called via a web request.

public class ResponsePackage  
{
    public List Errors { get; set; }

    public object Result { get; set; } 
}

This requires quite a bit of extra work on the client side to get at the Result object. Testing is also complicated because a test calling the action method directly get a different response than a request being rewritten.
The rewriting also applies to all responses from the WebApi.

I propose a slightly different solution.

Step 1

Add the FluentValidation.WebApi NuGet package to the Web Api project and wire it up in the WebApiConfig class.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //Fluent Validation
        config.Filters.Add(new ValidateModelStateFilter());
        FluentValidationModelValidatorProvider.Configure(config);
        
        //snip..    
    }
}
Step 2

Create a model and validator in a Models project.

[Validator(typeof(PersonCreateRequestModelValidator))] 
public class PersonCreateRequestModel
{
    public Guid PersonId { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}
	
public class PersonCreateRequestModelValidator : AbstractValidator
{
    //Simple validator that checks for values in Firstname and Lastname
    public PersonCreateRequestModelValidator()
    {
        RuleFor(r => r.Firstname).NotEmpty();
        RuleFor(r => r.Lastname).NotEmpty();
    }
}

Step 3

Create the Web Api endpoint.

public IHttpActionResult Post([FromBody]PersonCreateRequestModel requestModel)
{
    // If we get this far we have a vaild model.
    // If we then saved the person to the database we would get an id for the person and return it to the caller.
    requestModel.PersonId = Guid.NewGuid();

    return Ok(requestModel.PersonId);
}
Step 4

Create a client to call the Web Api endpoints. In my example I use a console app, but you could use MVC or another Web Api project.

Create a HttpClient client to call the web service.

private HttpClient GetHttpClient()
{
    var httpClient = new HttpClient();
    httpClient.BaseAddress = new Uri(@"http://localhost:5802/api/");
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    return httpClient;
}

Call the web service using the client and examine the response for success, HttpStatusCode.OK, or failure, any other status code.

private async <Task> PostToService(PersonCreateRequestModel model)
{
    var httpClient = GetHttpClient();
    string requestEndpoint = "person"; // full request will be http://localhost:5802/api/person
    HttpResponseMessage response = await httpClient.PostAsJsonAsync(requestEndpoint, model);

    WebApiResponse wrappedResponse;
    
    if (response.StatusCode == HttpStatusCode.OK)
    {
        var id = await response.Content.ReadAsAsync();
        wrappedResponse = new WebApiResponse(id, response.StatusCode);
    }
    else
    {
        var errors = await response.Content.ReadAsStringAsync();
        wrappedResponse = new WebApiResponse(errors, response.StatusCode, true);
    }
    return wrappedResponse;
}

Success or failure, I wrap the repsonse (in the client) without losing anything from the web service. WebApiResponse is a generic class and as such takes any type. The wrapped response is then returned to the caller to do with as they wish.

public class WebApiResponse
{
    public WebApiResponse(T apiResponse, HttpStatusCode httpStatusCode)
    {
        ApiResponse = apiResponse;
        HttpStatusCode = httpStatusCode;
    }

    public WebApiResponse(string error, HttpStatusCode httpStatusCode, bool isError) // isError is just a way to differentiate the two constructors. If <code>T</code> were a string this constructor would always be called. 
    {
        Error = error;
        HttpStatusCode = httpStatusCode;
    }
    public T ApiResponse { get; set; }
    public HttpStatusCode HttpStatusCode { get; set; }
    public string Error { get; set; }
}

The major benefits I see in the approach are that it is simple, very flexible, does not change anything coming back from the web service, testing is unaffected, and you are altering the Microsoft provided response pipeline.

Full source code here.

Web API 2 Controller with multiple get methods

I have two other posts on multiple GET methods, one for ASP.NET 5 Web Api, and another for Web Api 2.

It seems that every version of Web API changes how it handles default routes or route prefixes or whatever the next name will be.

I’ve written previously on how to handle multiple get methods in Asp.Net 5 Web API.

It’s a little different in Web Api 2.

using System.Web.Http;

namespace WebApiMultipleGets.Controllers
{
    [RoutePrefix("api/values")]
    public class ValuesController : ApiController
    {
        public string Get()
        {
            return "simple get";
        }

        [Route("geta")]
        public string GetA()
        {
            return "A";
        }

        [Route("getb")]
        public string GetB()
        {
            return "B";
        }

        [Route("getc")]
        public string GetC()
        {
            return "C";
        }

        [Route("getd")]
        public string GetD()
        {
            return "D";
        }
    }
}

Value cannot be null. Parameter name: constructor

Using Entity Framework I occasionally get the following error when reading from the database –
exceptionMessage=Value cannot be null.
Parameter name: constructor

My Person class looked like this –

    public class Person
    {
        public Person(string firstname, string lastname)
        {
             Firstname = firstname;
             Lastname = lastname;
        }

        public Guid PersonId { get; set; } 
        public string Firstname { get; set; } 
        public string Lastname { get; set; } 
        public DateTime SomeDate { get; set; }
     }

There is no way for Entity Framework to know how to instantiate this object because there is no empty constructor.

If you are following some of the principles of domain driven design you may not want a public empty constructor, no problem, make it private.

    public class Person
    {
        private Person(){} // Entity Framework queries will work now

        public Person(string firstname, string lastname)
        {
             Firstname = firstname;
             Lastname = lastname;
        }

        public Guid PersonId { get; set; } 
        public string Firstname { get; set; } 
        public string Lastname { get; set; } 
        public DateTime SomeDate { get; set; }
     }