Home > front end >  Calling an API via Azure Function
Calling an API via Azure Function

Time:12-20

I am trying to call an API inside an Azure HTTP Trigger. I have a .NET Core API that I need to call from an Azure Function. The API is working without an issue. When I am trying to implement the Trigger I am getting this error. Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'WebApplication1.Controllers.ContactsController' while attempting to activate 'FunctionApp1.Function1'.

.NET core API and Azure function are in the same solution but as different projects.

This is the implementation of trigger

namespace FunctionApp1
{
    public class Function1
    {
        private readonly ContactsController _contacts;

        public Function1(ContactsController _contacts)
        {
            this._contacts = _contacts;
        }

        [FunctionName("Function1")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            var response = await _contacts.GetContacts();

            return new OkObjectResult(response);
        }
    }
}

Let me know what is wrong with this. Thank you.

I tried the suggestion

namespace FunctionApp1
{
    public class Function1
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public Function1(IHttpClientFactory httpClientFactory)
        {
            this._httpClientFactory = httpClientFactory;
        }

        [FunctionName("Function1")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            var client = _httpClientFactory.CreateClient();
            var response = await client.GetAsync("https://localhost:7209/api/Contacts");

            return new OkObjectResult(response.ToString());
        }
    }
}

But now I am ending up with some response but not the response I want

{
    "version": "1.1",
    "content": {
        "headers": [
            {
                "key": "Content-Type",
                "value": [
                    "application/json; charset=utf-8"
                ]
            }
        ]
    },
    "statusCode": 200,
    "reasonPhrase": "OK",
    "headers": [
        {
            "key": "Date",
            "value": [
                "Mon, 19 Dec 2022 18:59:13 GMT"
            ]
        },
        {
            "key": "Server",
            "value": [
                "Kestrel"
            ]
        },
        {
            "key": "Transfer-Encoding",
            "value": [
                "chunked"
            ]
        }
    ],
    "trailingHeaders": [],
    "requestMessage": {
        "version": "1.1",
        "versionPolicy": 0,
        "content": null,
        "method": {
            "method": "GET"
        },
        "requestUri": "https://localhost:7209/api/Contacts",
        "headers": [],
        "properties": {},
        "options": {}
    },
    "isSuccessStatusCode": true
}

CodePudding user response:

This is not how you call a web API. The controller isn't a client, it belongs to the API project and although is declared public, has no meaning outside of the API project (and perhaps a unit test project that needs to instantiate the controller to test it, but that's nothing to do with this question). To call the API you need an HttpClient which makes a web request to the URL of the desired API operation.

The error you are getting is telling you that the Functions host doesn't have enough information to create an instance of the constructor dependency, in your case ContractsController. This is not useful to you though, what you actually need is an IHttpClientFactory:

public Function1(IHttpClientFactory httpClientFactory)
        {
            this._httpClientFactory = httpClientFactory;
        }

And use this to create a client to make the request:

var client = this._httpClientFactory.CreateClient();
var response = await client.GetAsync(...your URL);
var returnResult = await response.Content.ReadAsAsync<Whatever your return type is>();

The host still needs to be configured to inject the HttpClientFactory, so define a startup class in your function app if you don't already have one:

[assembly: FunctionsStartup(typeof(Startup))]

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddHttpClient();
    }
}

.AddHttpClient(); is a helper method provided by Microsoft.Extensions.Http to configure the dependency injection logic for the host to know how to inject HttpClients, see documentation for a full explanation.

  • Related