DEV Community

Cover image for How to Add Generated HttpClient to ASP.NET Core Dependency Injection (Right Way)
Dmitry Pavlov
Dmitry Pavlov

Posted on • Originally published at Medium on

5 2

How to Add Generated HttpClient to ASP.NET Core Dependency Injection (Right Way)

This How-To describes how to inject dependency to HttpClient you generated for PetStore API with OpenAPI (Swagger) Connected Service to ASP.NET Core application. The sample code is available in here.

OpenAPI (Swagger) Connected Service is a Visual Studio extension to generate C# HttpClient code for OpenAPI (formerly Swagger) web services with NSwag. Simply put, it is like kind old Add Service Reference for WCF or Add Web Reference for WSDL, but for JSON API we all deal with nowadays.

Follow 5 steps below to achieve this:

Step 1. Generate C# HttpClient class for PetStore API in your ASP.NET Core MVCweb application using OpenAPI (Swagger) Connected Service. See Getting Started section to install and run this Visual Studio extension.

Step 2. Add new file PetStoreClient.cs and make sure the class is marked as partial and has the same name and namespace as generated public partial class Client in PetStoreClient.Generated.cs. Also define the interface IPetStoreClient. The idea behind using the interface is to separate the methods you see where your client is used from what you don’t want to expose. In this sample we just expose the method to retrieve the number of pets sold by the store. So we define the method GetSoldPetsCount, which internally uses generated method for GET pet/findPetsByStatus endpoint. That is how it might look like:

using System.Collections.Generic;
using System.Threading.Tasks;
namespace Samples.AspNetCoreMvc.ClientInjectedToStartup.PetStore
{
/// <summary>This partial class allows to wrap and extend the generated client logic if you need that.</summary>
public partial class Client : IPetStoreClient
{
// Note: let's implement the interface methods we want to expose
public async Task<int> GetSoldPetsCountAsync()
{
ICollection<Pet> soldPets = await this.FindPetsByStatusAsync(new[] { Anonymous.Sold });
return soldPets.Count;
}
}
/// <summary>Interface defines what we want to expose in our appliction via dependency injection.</summary>
public interface IPetStoreClient
{
/// <summary>Returns number of all sold pets in the store.</summary>
Task<int> GetSoldPetsCountAsync();
// NOTE: you can also define here methods from generated Client partial class to expose them from interface.
}
}

Step 3. Now let’s use HttpClientFactory to inject the IPetStoreClient. Go to Startup.cs and add this to ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
...
// Inject generated PetStore client via using HttpClientFactory to implement resilient HTTP requests.
services.AddHttpClient<IPetStoreClient, Client>((provider, client) =>
{
client.BaseAddress = new System.Uri("https://petstore.swagger.io/v2/");
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Step 4. In Index action in HomeController.cs let’s inject IPetStoreClient and pass the number of sold pets to the View:

public class HomeController : Controller
{
private readonly IPetStoreClient _petStoreClient;
public HomeController(IPetStoreClient petStoreClient)
{
_petStoreClient = petStoreClient;
}
public async Task<IActionResult> Index()
{
TempData["SoldPetsCount"] = await _petStoreClient.GetSoldPetsCountAsync();
return View();
}
...
}

Step 5. To display the number of sold pets on the default site page add this code to View\Home\Index.cshtml:

@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
<p>We have injected Pet Store to our DI and retrieved data from API.</p>
<ul>
<li>Number of pets sold: @TempData["SoldPetsCount"]</li>
</ul>
</div>

That’s it! We have injected generated client for PetStore API to ASP.NET Core application via the dependency injection (DI) software design pattern.

Enjoy coding with the Coding Machine

Top comments (2)

Collapse
 
angellaguna profile image
AngelLaguna

Hi. I have a question,
if my response is a Ok and BadRequest,
how can i get the data this request?

Collapse
 
dr_dimaka profile image
Dmitry Pavlov

If you are generating with NSwag for your API controller - add attributes and return the object from the action - something like this:

[SwaggerResponse(HttpStatusCode.OK, typeof(MyOkResponse))]
[SwaggerResponse(HttpStatusCode.BadRequest, typeof(string))]
public async Task<ActionResult<MyOkResponse>>  GetMyResponseAsync(CancellationToken token)
{
  var myResponse = await GetMyDataAsync();
  try { 
    return OK(myResponse);
  } catch (Exception ex) {
    return BadRequest(ex.Message);
  }
}
Enter fullscreen mode Exit fullscreen mode

In this case NSwag will know how to interpret your responses - see in generated code how to retrieve error details from ApiException generated client will throw for any non OK response you defined.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more