Complex Type Action Parameters with ComplexTypeAwareActionSelector in ASP.NET Web API - Part 2

In this post, we will see how ComplexTypeAwareActionSelector behaves under the covers to involve complex type action parameters during the action selection process.
2012-10-08 06:03
Tugberk Ugurlu


In my previous post on complex type action parameters with ComplexTypeAwareActionSelector in ASP.NET Web API, I showed how to leverage the ComplexTypeAwareActionSelector from WebAPIDoodle project to involve complex type action parameters during the action selection process. In this post, we will go into details to see how ComplexTypeAwareActionSelector behaves under the covers.

Assuming that we have a Person class as below:

public class Person {

    public int FooBar;

    public Nullable<int> Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
        
    public string FullName { 

        get {
            return string.Format("{0} {1}", Name, Surname);
        }
    }

    [BindingInfo(NoBinding = true)]
    public string FullName2 { get; set; }

    public Country Country { get; set; }

    internal int Foo { get; set; }

    public bool IsLegitPerson() {

        return Name.Equals("tugberk", StringComparison.OrdinalIgnoreCase);
    }
}

public class Country {

    public int Id { get; set; }
    public string Name { get; set; }
    public string ISOCode { get; set; }
}

In a real world scenario, we wouldn't use the Person class to bind its values from the URI but bare with me for sake of this demo. Person class has five publicly-settable properties: Id, Name, Surname, FullName2 and Country. It also has internally-settable property called Foo. There are also one read-only property (FullName) and one public field (FooBar). Besides those, the FullName2 property has been marked with WebAPIDoodle.BindingInfoAttribute by setting its NoBinding property to true.

Let’s also assume that we have the below controller and action.

public class FooBarController : ApiController {

    public IEnumerable<FooBar> Get([FromUri]Person person) { 

        //...
    }
}

Now, the question is how ComplexTypeAwareActionSelector behaves here and which members of the Person class are going to be involved to perform the action selection. To perform this logic, the ComplexTypeAwareActionSelector uses two helper methods as below:

internal static class TypeHelper {

    internal static bool IsSimpleType(Type type) {

        return type.IsPrimitive ||
                type.Equals(typeof(string)) ||
                type.Equals(typeof(DateTime)) ||
                type.Equals(typeof(Decimal)) ||
                type.Equals(typeof(Guid)) ||
                type.Equals(typeof(DateTimeOffset)) ||
                type.Equals(typeof(TimeSpan));
    }

    internal static bool IsSimpleUnderlyingType(Type type) {

        Type underlyingType = Nullable.GetUnderlyingType(type);
        if (underlyingType != null) {
            type = underlyingType;
        }

        return TypeHelper.IsSimpleType(type);
    }
}

These two methods belong to ASP.NET Web API source code but they are internal. So, I ported them to my project as they are. As you can see, IsSimpleType method accepts a Type parameter and determines if the type is a simple or primitive type. The IsSimpleUnderlyingType method, on the other hand, looks if the Type is Nullable type. If so, it looks at the underlying type to see if it is a simple type or not. This is how the ComplexTypeAwareActionSelector determines if a parameter is simple type or not.

When the ComplexTypeAwareActionSelector sees a complex type action parameter, it hands that type to another private method to get the useable properties. To mimic how that private helper method filters the properties, I created the a little console application which holds the actual filter logic.

class Program {

    static void Main(string[] args) {

        Console.Write(Environment.NewLine);
        Console.WriteLine("===============================================");
        Console.WriteLine("========This is the actual logic in use========");
        Console.WriteLine("===============================================");

        var propInfos = from propInfo in typeof(Person).GetProperties()
                        where TypeHelper
                              .IsSimpleUnderlyingType(propInfo.PropertyType) && 
                              propInfo.GetSetMethod(false) != null
                              
                        let noBindingAttr = propInfo
                            .GetCustomAttributes().FirstOrDefault(attr => 
                                attr.GetType() == typeof(BindingInfoAttribute)) 
                                    as BindingInfoAttribute
                                    
                        where (noBindingAttr != null) 
                              ? noBindingAttr.NoBinding == false 
                              : true
                              
                        select propInfo;

        foreach (var _propInfo in propInfos) {

            Console.WriteLine(_propInfo.Name);
        }

        Console.ReadLine();
    }
}

Here is what it is doing here for the Person type:

  • It first gets all the public properties of the Person class with GetProperties method of the Type class. So, the ForBar field and the Foo property is ignored.
  • Secondly, it looks if the property is simple underlying type and publicly-settable. If any one of them is not applicable, it ignores them. In our case here, the FullName property, which is a read-only property, and the Country property, which is a complex type property, are ignored.
  • As a last step, it looks at the attributes of the each filtered property. If the property is marked with WebAPIDoodle.BindingInfoAttribute and the BindingInfoAttribute’s NoBinding property is set to true, the property gets ignored. In our case here, the FullName2 property will be ignored.

If we run this little console application, we will see the following result:

SNAGHTML12a04389

As a result, the Id, Name and Surname properties will be considered during the action selection. I would like to point out couple of things before finishing up this post:

  • This is a one-time operation per controller action. For example, when we first fire up our ASP.NET Web API application and send a request which is eventually going to correspond to FooBarController, the action selector will look at all the actions under the FooBarController and performs the above logic along with others and cache lots of stuff including the above logic. So, when you hit the FooBarController next time, this process won’t be run and the result will be pulled directly from the cache.
  • The WebAPIDoodle.BindingInfoAttribute lives inside a separate package named as WebAPIDoodle.Meta. The WebAPIDoodle.Meta package contains some runtime components such as Attributes, Interfaces. This assembly has no dependency on ASP.NET Web API so that it would be easy to reference this on Model or Domain Layer projects.

Happy coding and give feedback for this little feature :)

Complex Type Action Parameters with ComplexTypeAwareActionSelector in ASP.NET Web API - Part 1

We will see how to make complex type action parameters play nice with controller action selection in ASP.NET Web API by using ComplexTypeAwareActionSelector from WebAPIDoodle NuGet package.
2012-10-07 10:56
Tugberk Ugurlu


Couple of days ago, I wrote a blog post on complex type action parameters and controller action selection with ASP.NET Web API with a solution that I’ve come up with and I encourage you to check that blog post out to get a sense of what this is really about. However, that solution was sort of noisy. Yesterday, I tweaked the ComplexTypeAwareActionSelector implementation a bit and now it directly supports the complex type action parameters without any additional attributes for the action methods. In this post, we will see how we can use it and in the next post, we will see how it works under the covers.

First of all, install the latest WebAPIDoodle package rom the Official NuGet feed:

PM> Install-Package WebAPIDoodle

Let’s go through the scenario briefly. Assume that we have the following controller with two action methods that are expected to serve for different GET requests:

public class CarsByCategoryRequestCommand {

    public int CategoryId { get; set; }
    public int Page { get; set; }

    [Range(1, 50)]
    public int Take { get; set; }
}

public class CarsByColorRequestCommand {

    public int ColorId { get; set; }
    public int Page { get; set; }

    [Range(1, 50)]
    public int Take { get; set; }
}

[InvalidModelStateFilter]
public class CarsController : ApiController {

    public string[] GetCarsByCategoryId(
        [FromUri]CarsByCategoryRequestCommand cmd) {

        return new[] { 
            "Car 1",
            "Car 2",
            "Car 3"
        };
    }

    public string[] GetCarsByColorId(
        [FromUri]CarsByColorRequestCommand cmd) {

        return new[] { 
            "Car 1",
            "Car 2"
        };
    }
}

If we now send a GET request to /api/cars?colorId=23&page=2&take=12 with the default action selector registered, we would get the ambiguity error message because the default action selector doesn’t consider the complex type action parameters while performing the action selection.

Let’s replace the default action selector with our ComplexTypeAwareActionSelector as below. Note that ComplexTypeAwareActionSelector preserves all the features of the ApiControllerActionSelector.

protected void Application_Start(object sender, EventArgs e) {

    var config = GlobalConfiguration.Configuration;
    config.Routes.MapHttpRoute(
        "DefaultApiRoute",
        "api/{controller}/{id}",
        new { id = RouteParameter.Optional }
    );

    // Replace the default action IHttpActionSelector with
    // WebAPIDoodle.Controllers.ComplexTypeAwareActionSelector
    config.Services.Replace(
        typeof(IHttpActionSelector),
        new ComplexTypeAwareActionSelector());
}

As explained inside the previous related post, we previously had to mark the action methods with UriParametersAttribute to give a hint about the action parameters we want to support. However, with the current implementation of the the ComplexTypeAwareActionSelector, it just works as it is. Only thing required to perform is to mark the complex action parameter with FromUriAttribute. By marking the complex type parameters with FromUriAttribute, you are making it possible to bind the route and query string values.

After replacing the default action selector with our own implementation, we will see it working if we send a GET request to /api/cars?colorId=23&page=2&take=12.

image

Now, let’s send a request to /api/cars?categoryId=23&page=2&take=12 and see what we will get back:

image

Working perfectly as expected. The ComplextTypeAwareActionSelector considers simple types inside a complex type parameter which are all primitive .NET types, System.String, System.DateTime, System.Decimal, System.Guid, System.DateTimeOffset, System.TimeSpan and underlying simple types (e.g: Nullable<System.Int32>).

In the next post, we will see how ComplextTypeAwareActionSelector works and behaves with complex type action parameters. Stay tuned! ;)

2012 Microsoft ASP.NET/IIS MVP Award

Yesterday, I received an awesome e-mail telling me that I have been given the Microsoft MVP award on ASP.NET/IIS for 2012.
2012-10-02 18:08
Tugberk Ugurlu


mvp_logo

Yesterday, I received an awesome e-mail telling me that I have been given the Microsoft MVP award on ASP.NET/IIS. :) This was obviously a great news for me because this is my first time being an MVP. If you wonder what the heck is Microsoft MVP Award program is, here is the quote from the official MVP Overview page:

"The Microsoft Most Valuable Professional (MVP) Award is our way of saying thank you to exceptional, independent community leaders who share their passion, technical expertise, and real-world knowledge of Microsoft products with others.

Nearly two decades ago, we awarded 37 technical community leaders as MVPs. Today, there are more than 4,000 MVPs worldwide. They represent more than 90 countries, speak over 40 languages, answer more than 10 million questions a year, and are awarded in almost 90 Microsoft technologies—reflecting the breadth of our products and our global communities."

Microsoft developer community is beyond huge. So many brilliant developers share their knowledge through blogs, webcasts, podcasts, conference talks, user group meetings. Being part of this community has been always a fun but with this award, this fun is now doubled. However, I have never seen the MVP award as a target. I didn’t do anything special to get this award (well, except for filling the evaluation form). I just did what I love and that was enough. I love spending time on Stackoverflow, I love writing blog posts and I love helping others if I can.

Nearly for four years now, I have been trying to find my way with ASP.NET and its sub components, such as ASP.NET MVC, ASP.NET Web API, SignalR and I can see that the product has been evolved so much in a positive direction. Not to mention some huge steps that have been taken such as making nearly the 90% of the ASP.NET stack open source on Codeplex. Being able to see how the product grows commit by commit is simply awesome. This improvements made it possible for me to create better software solutions for the company I work for. Besides that, other Microsoft products such as Window Azure took me and my company to the next level.

I would like to especially thank all the developers at Microsoft, especially the ASP.NET, IIS and Windows Azure team members for the great products they build and the continuous support whenever we need it. I also want to thank all of the developers in this community for sharing their valuable knowledge, answering questions on forums and Q&A sites. I should admit that I am learning a lot by looking at other people’s code and if they weren’t sharing those, I wouldn’t be the developer as I am today.

Lastly, I would like to thank my lovely fiancé Nihan for her support in my life; especially for listening to me talking about tech stuff even if she has no idea about what I say 99% of the time. :)

I am hoping that I will never lose this award and I want to keep getting it every year :)

Complex Type Action Parameters and Controller Action Selection with ASP.NET Web API

How to use complex type action parameters in ASP.NET Web API and involve them inside the controller action selection logic
2012-09-30 19:04
Tugberk Ugurlu


If you are familiar with ASP.NET MVC and trying to find your way with ASP.NET Web API, you may have noticed that the default action selection logic with ASP.NET Web API is pretty different than the ASP.NET MVC's. First of all, the action parameters play a huge role on action selection in ASP.NET Web API. Consider the following controller and its two action methods:

public class CarsController : ApiController { 

    //GET /api/cars?categoryId=10
    public string[] GetCarsByCategoryId(int categoryId) { 
        
        return new[] { 
            "Car 1",
            "Car 2",
            "Car 3"
        };
    }
    
    //GET /api/cars?colorId=10
    public string[] GetCarsByColorId(int colorId) { 
        
        return new[] { 
            "Car 1",
            "Car 2"
        };
    }
}

This doesn’t going to cause the action ambiguity because the action parameter names are different. The default action selector (ApiControllerActionSelector) going to extract the action parameter names and try to match those with the URI parameters such as query string and route values. So if a GET request comes to /api/cars?categoryId=10, the GetCarsByCategoryId action method will be invoked. If a GET request comes to /api/cars?colorId=10 in this case, the GetCarsByColorId action method will be called.

It's possible to use complex types as action parameters for GET requests and bind the route and query string values by marking the complex type parameters with FromUriAttribute. However, the default action selection logic only considers simple types which are System.String, System.DateTime, System.Decimal, System.Guid, System.DateTimeOffset and System.TimeSpan. For example, if you have GetCars(Foo foo) and GetCars(Bar bar) methods inside your controller, you will get the ambiguous action error as the complex types are completely ignored by the ApiControllerActionSelector.

Let’s take the following as example here:

public class CarsByCategoryRequestCommand {

    public int CategoryId { get; set; }
    public int Page { get; set; }

    [Range(1, 50)]
    public int Take { get; set; }
}

public class CarsByColorRequestCommand {

    public int ColorId { get; set; }
    public int Page { get; set; }

    [Range(1, 50)]
    public int Take { get; set; }
}

public class CarsController : ApiController {

    public string[] GetCarsByCategoryId(
        [FromUri]CarsByCategoryRequestCommand cmd) {

        return new[] { 
            "Car 1",
            "Car 2",
            "Car 3"
        };
    }

    public string[] GetCarsByColorId(
        [FromUri]CarsByColorRequestCommand cmd) {

        return new[] { 
            "Car 1",
            "Car 2"
        };
    }
}

We are not performing any logic inside the action here but you can understand from the action parameter types that we are aiming to perform pagination here. So, we are receiving the inputs from the consumer. We can use simple types directy as action parameters but there is no built-in way to validate the simple types and I haven’t found an elegant way to hook something up for that. As a result, complex type action parameters comes in handy in such cases.

If we now send a GET request to /api/cars?colorId=23&page=2&take=12, we would get the ambiguity error message:

image

To workaround this issue, I created a new action selector which has the same implementation as the ApiControllerActionSelector and a few tweaks to make this feature work. It wasn’t easy at all. The ApiControllerActionSelector is not so extensible and I had to manually rewrite it (honestly, I didn’t directly copy-paste. I rewrote the every single line). I also thought that this could make it into the framework. So, I sent a pull request which got rejected:  3338. There is also an issue open to make the default action selector more extensible: #277. I encourage you to go and vote!

So, what can we do for now to make this work? Go and install the latest WebAPIDoodle package from the Official NuGet feed:

PM> Install-Package WebAPIDoodle

This package has a few useful components for ASP.NET Web API and one of them is the ComplexTypeAwareActionSelector. First of all, we need to replace the default action selector with our ComplexTypeAwareActionSelector as below. Note that ComplexTypeAwareActionSelector preserves all the features of the ApiControllerAction selector.

protected void Application_Start(object sender, EventArgs e) {

    var config = GlobalConfiguration.Configuration;
    config.Routes.MapHttpRoute(
        "DefaultApiRoute",
        "api/{controller}/{id}",
        new { id = RouteParameter.Optional }
    );

    // Replace the default action IHttpActionSelector with
    // WebAPIDoodle.Controllers.ComplexTypeAwareActionSelector
    config.Services.Replace(
        typeof(IHttpActionSelector),
        new ComplexTypeAwareActionSelector());
}

This package also contains an attribute named UriParametersAttribute which accepts a params string[] parameter. We can apply this attribute to action methods and pass the parameters that we want to be considered during the action selection. The below one shows the sample usage for our above case:

public class CarsController : ApiController {

    [UriParameters("CategoryId", "Page", "Take")]
    public string[] GetCarsByCategoryId(
        [FromUri]CarsByCategoryRequestCommand cmd) {

        return new[] { 
            "Car 1",
            "Car 2",
            "Car 3"
        };
    }

    [UriParameters("ColorId", "Page", "Take")]
    public string[] GetCarsByColorId(
        [FromUri]CarsByColorRequestCommand cmd) {

        return new[] { 
            "Car 1",
            "Car 2"
        };
    }
}

If we now send the proper GET requests as below, we should see it working:

image

image

You can also grab the sample to see this in action. I should also mention that I am not saying that this is the way to go. Clearly, this generates a lot of noise and we can do better here. The one solution would be to inspect the simple type properties of the complex type action parameter without needing the UriParametersAttribute.

Asynchronous .NET Client Libraries for Your HTTP API and Awareness of async/await's Bad Effects

Writing asynchronous .NET Client libraries for your HTTP API and using asynchronous language features (aka async/await) and some deadlock issue you might face.
2012-09-21 06:34
Tugberk Ugurlu


Haven’t you shot yourself in the foot yet with async/await? If not, you are about to if you are writing a client library for your newly created ASP.NET Web API application with .NET 4.5 using new asynchronous language features.

I wrote a blog post couple of months ago on the importance of Current SynchronizationContext and the new C# 5.0 asynchronous language Features (aka async/await). I wrote that post just after I watched the The zen of async: Best practices for best performance talk of Stephen Toub on //Build 2011 and that was one of the best sessions that I was and still am glad to watch. I learnt so many things from that session and some of them was amazingly important.

Filip Ekberg also has a very nice and useful blog post which has an identical title as my previous post on the topic: Avoid shooting yourself in the foot with Tasks and Async.

The post was pointing out that it is extremely easy to end up with a deadlock if you are not careful enough. The post explains every details but if want to recap shortly, here it is:

When you are awaiting on a method with await keyword, compiler generates bunch of code in behalf of you. One of the purposes of this action is to handle synchronization with the UI thread. The key component of this feature is theSynchronizationContext.Current which gets the synchronization context for the current thread. SynchronizationContext.Current is populated depending on the environment you are in. The GetAwaiter method of Task looks up for SynchronizationContext.Current. If current synchronization context is not null, the continuation that gets passed to that awaiter will get posted back to that synchronization context.

When consuming a method, which uses the new asynchronous language features, in a blocking fashion, you will end up with a deadlock if you have an available SynchronizationContext. When you are consuming such methods in a blocking fashion (waiting on the Task with Wait method or taking the result directly from the Result property of the Task), you will block the main thread at the same time. When eventually the Task completes inside that method in the threadpool, it is going to invoke the continuation to post back to the main thread because SynchronizationContext.Current is available and captured. But there is a problem here: the UI thread is blocked and you have a deadlock!

The post also has a sample but I want dig deep into this. As you all know, ASP.NET Web API RTW version has been shipped couple of weeks ago and we may have started to take advantage of this framework to build our HTTP-based lightweight APIs. You might be using another framework to create your APIs or you might be maintaining an existing one. No matter which category you put yourself in, you are likely to build platform specific client libraries for your API. If you are going to target .NET framework, I am 90% sure that you want your client library to be asynchronous and new HttpClient will just give you that option.

I have started writing a simple blog engine for myself called MvcBloggy nearly a year ago and after the RTW release of the ASP.NET MVC 4 and ASP.NET Web API, I decided to try something different and expose the data through HTTP. So, my ASP.NET MVC application won’t know anything about where my data is store or how I retrieve it. It is just going to consume the HTTP APIs. The application is shaping up nicely and I even started to build my .NET client for the API as well.

Couple of days ago, Ben Foster (a brilliant developer) raised a question on Twitter about consuming asynchronous methods on ASP.NET Web Pages application and I also wondered about that. Then, we looked around a bit and also contacted with Erik Porter (@HumanCompiler), Program Manager on the ASP.NET team, and he confirmed that it is not possible today. He encouraged us to file an issue and we did (#418). This got me thinking about my little project’s .NET client, though. What if I wanted to create a blog web site with ASP.NET Web Pages by consuming the .NET client of my blog engine? I have no option rather than consuming the methods in a blocking fashion but with my current implementation, I am not able to do that because I will end up with deadlocks. Let me prove that to you with a little example which you can also find up on GitHub: AsyncAwaitForLibraryAuthors.

Assuming we have a little API which returns back a list of cars and we want to build a .NET client to consume the HTTP API and abstracts all the lower level HTTP stuff away. The one that I created is as below (it is a simple one for the demo purposes):

public class Car {

    public int Id { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public float Price { get; set; }
}

public class SampleAPIClient {

    private const string ApiUri = "http://localhost:17257/api/cars";

    public async Task<IEnumerable<Car>> GetCarsAsync() {

        using (HttpClient client = new HttpClient()) {

            var response = await client.GetAsync(ApiUri);

            // Not the best way to handle it but will do the work for demo purposes
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsAsync<IEnumerable<Car>>();
        }
    }
}

We leveraged the new asynchronous language features and we were able to write a small amount of code to get the job done. More importantly, we are making the network call and the deserialization asynchronously. As we know from the earlier sentences that if there is a SynchronizationContext available for us, the code that the compiler is generating for us will capture that and post the continuation back to that context to be executed. Keep this part in mind. I put this little class inside a separate project called SampleAPI.Client and reference this from my web clients. I have created two clients: one ASP.NET MVC and one ASP.NET Web Pages applications.

In my ASP.NET MVC 4 application, I have a controller which has two actions. One of these actions will call the API asynchronously and one of will do the same by blocking:

public class HomeController : Controller {

    public async Task<ViewResult> CarsAsync() {

        SampleAPIClient client = new SampleAPIClient();
        var cars = await client.GetCarsAsync();

        return View("Index", model: cars);
    }

    public ViewResult CarsSync() {

        SampleAPIClient client = new SampleAPIClient();
        var cars = client.GetCarsAsync().Result;

        return View("Index", model: cars);
    }
}

Our view is also so simple as follows:

@model IEnumerable<SampleAPI.Client.Car>
@{
    ViewBag.Title = "Home Page";
}

<h3>Cars List</h3>

<ul>
    @foreach (var car in Model) {
        <li>
            @car.Make, @car.Model (@car.Year) - @car.Price.ToString("C")
        </li>    
    }
</ul>

When we navigate to /home/CarsAsync, we will get back the result.

image

However, when we navigate to /home/CarsSync to invoke the CarsSync method, we will see that the page will never come back because we just introduced a deadlock due to the reasons we have explained earlier. Let’s have a look at the Web Pages sample:

@{
    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "Home Page";

    SampleAPI.Client.SampleAPIClient client = new SampleAPI.Client.SampleAPIClient();
    var cars = client.GetCarsAsync().Result;
}

<h3>Cars List</h3>

<ul>
    @foreach (var car in cars) {
        <li>
            @car.Make, @car.Model (@car.Year) - @car.Price.ToString("C")
        </li>    
    }
</ul>

This page is also not going to respond because Web Pages runs under ASP.NET and ASP.NET has a SynchronizationContext available.

When we take a look at our GetCarsAsync method implementation, we will see that it is completely unnecessary for us to get back to current SynchronizationContext because we don’t need anything from the current context. This is good because it is not our (I mean our .NET client’s) concern to do anything under the current SynchronizationContext. It is, on the other hand, our consumer’s responsibility. Stephen Toub said something in his talk on //Build 2011 and the words not the same but it expresses the meaning of the below sentences:

If you are a library developer, the default behavior which await gives you is nearly never what you want. However, if you are a application developer, the default behavior will nearly always what you want.

I, again, encourage you to check that video out.

The solution here is simple. When we are creating our libraries, we just need to be more careful and think about the usage scenarios. In our case here, we need to suppress the default SynchronizationContext behavior that the compiler is generating for us. We can achieve this with ConfigureAwait method of the Task class which was introduced with .NET 4.5. The ConfigureAwait method accepts a Boolean parameter named as continueOnCapturedContext. We can pass false into this method not to marshal the continuation back to the original context captured and our problem would be solved. Here is the new look of our .NET client for our HTTP API.

public class SampleAPIClient {

    private const string ApiUri = "http://localhost:17257/api/cars";

    public async Task<IEnumerable<Car>> GetCarsAsync() {

        using (HttpClient client = new HttpClient()) {

            var response = await client.GetAsync(ApiUri)
                .ConfigureAwait(continueOnCapturedContext: false);

            // Not the best way to handle it but will do the work for demo purposes
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsAsync<IEnumerable<Car>>()
                .ConfigureAwait(continueOnCapturedContext: false);
        }
    }
}

When we now run our Web Pages application, we will see the web site working nicely (same is also applicable for the CarsSync action method of our ASP.NET MVC application).

image

If you are going to write a .NET client for your company’s big HTTP API using new asynchronous language features, you might want to consider these facts before moving on. Otherwise, your consumers will have hard time understanding what is really going wrong.