20

I'm writing ASP.Net MVC Core 2.2 Web App. I need to get data from another web server with HTTP or HTTPS. How should I do this?

I wrote code using HttpClient.

I have a Controller that gets a message and it works fine but, should I be constructing HttpClient?

[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    private readonly IHostingEnvironment _env;
    private readonly ILogger _logger;
    private readonly IUpdateService _updateService;

    public MyController(
        IHostingEnvironment env,
        ILogger<MyController> logger,
        IUpdateService updateService)
    {
        _env = env;
        _logger = logger;
        _updateService = updateService;
    }

    // POST api/values
    [HttpPost]
    public async Task<IAsyncResult> Post([FromBody]Update update)
    {
        using (HttpClient Client = new HttpClient())
        {
            HttpResponseMessage result = Client.GetAsync(uri).Result;
            switch (result.StatusCode)
            {
                case HttpStatusCode.Accepted:
                    return true;
                case HttpStatusCode.OK:
                    return true;
                default:
                    return false;
            }
        }
    }
}
Mohamad Mousheimish
  • 1,641
  • 3
  • 16
  • 48
Faraz
  • 834
  • 1
  • 6
  • 14
  • 1
    please, don't use using because of the IDispose pattern.. https://stackoverflow.com/a/54707165/1498669 – Bernhard Mar 28 '23 at 08:05

1 Answers1

48

Microsoft documentation here.

  1. Register the HttpClient in ConfigureServices.

    1a. for typed clients

    services.AddHttpClient<ITypedClientService, TypedClientService>();
    

    1b. for named clients

    services.AddHttpClient("someClient", c =>
    {
        c.BaseAddress = new Uri("https://someaddress.com/");
    });
    

    1c. for Basic usage

    services.AddHttpClient();
    
  2. Inject the HttpClient into your controller.

    [ApiController]
    public class BotController : ControllerBase
    {
        ...
    

    2a. for typed clients

        public BotController(..., ITypedClientService httpClient, ...)
        {
            ...
            _httpClient = httpClient;
            ...
        }
    

    2b. for named clients

        public BotController(..., IHttpClientFactory clientFactory, ...)
        {
            ...
            _httpClient = clientFactory.createClient("someClient");
            ...
        }
    

    2c. for Basic usage

        IHttpClientFactory _clientFactory
    
        public BotController(..., IHttpClientFactory clientFactory, ...)
        {
            ...
            _clientFactory = clientFactory; 
            ...
        }
    
        [HttpPost]
        public async Task<IActionResult> Post([FromBody]Update update)
        {
            ...
            var request = new HttpRequestMessage(
                HttpMethod.Get, 
                "https://someaddress.com/api/resource");
            request.Headers.Add("Accept", "application/vnd.github.v3+json");
            request.Headers.Add("User-Agent", "YourApp");
            var client = _clientFactory.createClient();
            var response = await client.SendAsync(request);
            ...
        }
    

Do not construct HttpClient yourself, new is glue. Let HttpClientFactory and the framework mangage the lifetimes and instantiation.

Note, With Basic Usage you are dodging the benefits of configuring policies for defined clients.

Jodrell
  • 34,946
  • 5
  • 87
  • 124