how-to-consume-azurefunction

How to Consume Azure Function

In this post I am going to create an Azure function by using Visual Studio 2022, and then  publish the code to Azure.  After this I will call this function by using ASP.NET Core Web application.

Azure Functions lets you execute code in a Serverless environment without having  a VM or publish a web application.

The steps we are going here:

  1. Create Azure Function in Visual Studio 2022
  2. Deploy Function to Azure App Service Via VS
  3. Create Asp.net web application in Visual Studio
  4. Test WebApplication to consume the Fuction App

Create Azure Function in Visual Studio 2022

pen Visual Studio: Create New Project and in the Search area, Search Azure functions, then select Azure Functions template which is shown in the following:

how-to-consume-azurefunction-1.png
Creating Azure functions in Visual Studio 2022

Press to Next button and in the next image give project name (in my case EmployFunctionsApp) and selection .

Press to Next and choose .NET 6, Http Trigger, check the checkbox, Use Azurite for runtime storage account (AzureWebJobsStorage).

how-to-consume-azurefunction-2.png
Creating Employee Function App

and press to Create button to create the project. A default template is created. In this default template change the name of file: Function1 to EmployeeFunction.cs  as shown in  follow image:

how-to-consume-azurefunction-3.png
Default template of Azure Function in Visual Studio

In this default template project there is 3 files: host.json, local.settings.json and EmployeeFunctions.cs.

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace EmployeeFunctionApp
{
public static class EmployeeFunctions
{
[FunctionName("EmployeeFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
}

The code is self explory.  Now let us  run this project in Visual Studio.

how-to-consume-azurefunction-4.png
Running Function app in Visual studio

This give us an URL: http://localhost:7071/api/EmployeeFunction.

Start browser with this URL and give a name with value as parameter (e.g. name = “Joe Frank” as follow:

http://localhost:7071/api/EmployeeFunction?Name=”Joe Frank”

As you see the output is:

Hello, “Joe Frank”. This HTTP triggered function executed successfully.

Now we want to develop further this project to get a list of Employees in a company.

In this post, I want to create a simple function that returns a list of Employees requests.

I need to add a entity class for EmployeeRequest.cs to this project:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EmployeeFunctionApp
{
public class EmployeeRequest
{
[JsonProperty(PropertyName = "employeeId")]
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
}
}

In the EmployeeFunction class add the following code:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Xml.Linq;
namespace EmployeeFunctionApp
{
public static class EmployeeFunction
{
[FunctionName("EmployeeFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
List<Employee> emplist = null;
string EmployeeId = string.Empty;
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
EmployeeId = data?.employeeId;
// create a list of Employee
emplist = new List<Employee>();
for (int i = 1; i < 5; i++)
{
emplist.Add(new Employee() { EmployeeId = "10", EmployeeName = $"Employee {i}" });
}
if(emplist != null)
return (ActionResult)new OkObjectResult(emplist);
return new BadRequestObjectResult("Please pass a employee Id in the request body");
}
}
}

The code above first creates four Employees and then returns a list of employees.

To create more employees you can use Postman and to create more Employees.

Testing locally from Visual Studio:

how-to-consume-azurefunction-6.png
Testing locally of EmployeeFunction

Start web browser with  URL: http://localhost:7071/api/EmployeeFunction, then you see list of Employees as follow:

how-to-consume-azurefunction-7.png
Shows the output as JSON format

As you see the list of Employees are showing in JSON format.

Now we have created a Azure Function App (EmployeeFunction), the next step is to deploy this function to Azure.

Deploy Function to Azure via Visual Studio

In Visual Studio select project (EmployeeFunctionApp) and press to the Publish menu, and then select Azure.. as follow:

how-to-consume-azurefunction-8.png
Publishing to Azure from Visual Studio

Press to Next and in the Next image select Azure Function App (Windows) and press to Next. Click on Subscription and choose right subscription that you have on Azure (Alternative create a free subscription), then shows  your Subscription (in my case, Azure Subscription 1), press to Create new Resources and fill in the filled as shown in the following image:

how-to-consume-azurefunction-9.png
Creating Resources for Azure function

Press to Create button, it takes a little time to deploy to Azure. Press to Finnish button. It creates an App Service  Azure and our Function is deployed to Azure as shown in in the following image:

how-to-consume-azurefunction-10.png
Azure Function is published to Azure

As you see on right under Properties, PublishProfiles folder is created which contains publishing information and configuration. Edit User name and Password and change them and remember the password

Press to Publish button on the upper of left side, it takes a while and trying to load the result in the browser, but it showed Error: An Error  is occurred : failed with HTTP status code Unauthorized.

To solve this problem, I have backed to the Auto generated user name and password by editing Username and pressing to the Attempt to retrieve credetials from Azure  and press to Save as shown in the following image:

how-to-consume-azurefunction-11.png
Attempt to retrieve credentials from Azure

Press to Publish button again and this time you see that Publishing is succeed. and shown the output of publish in Visual Studio:

Publish: 1 succeeded, 0 failed, 0 skipped ==========
Waiting for Function app to be ready…
Function app is ready

Now go to the Azure portal and select All Resources and then press to the Function name: EmployeeFunctionApp20221212142311 shown in the following image:

how-to-consume-azurefunction-12.png
Function App in Azure Portal

If you click on the URL on Azure portal then you can get: Your Functions 4.0 app is up and running.

The most HTTP trigger templates require an API key in the request. So, your HTTP request normally looks like the following URL:
https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?code=<API_KEY>

After publishing function, we  need to find keys, which  are stored as part of  function app in Azure. To view the keys, navigate to the Function app in Azure portal and under Function select

how-to-consume-azurefunction-13.png
Find App Keys for Function
Click on the “Hiden value: click to show value” for -master, then it show the value of key, Copy and Save this value. For my case the key value is:

“e27TJNYCWK3p7LFLrEEWpVWKQoF2hXNervm_XhY7XgxUAzFu1hyx8Q==”

Testing in the Function in Azure:
 Start browser with the following URL which contains the Code=App key value.
https://employeefunctionapp20221212142311.azurewebsites.net/api/EmployeeFunction?code=e27TJNYCWK3p7LFLrEEWpVWKQoF2hXNervm_XhY7XgxUAzFu1hyx8Q==

The result is:

how-to-consume-azurefunction-14.png
Testing Azure Function after Deploy to Azure

Now we have published our Function to Azure App Service and tested it and it is working as local.

The Source code of Function App can be found in my Github

Next step is to create Web App to call Azure function:

Create ASP.NET Core Web App to call Azure function

In the Visual Studio, select solution and Add, choose New project, Select template: ASP.NET Core Web App and then press Next:

Give project name: EmployeeWebApplication and location the same location Azu reFunctions then press to Next button, press to Create button to create the solution template  as shown in the following image:

/how-to-consume-azurefunction-15.png
WebApplication : EmployeeWebApplication Solution project is created

In the new project open appsettings.json file add the Azure Function URL  as following:

"AppSettings": {
"AzureFunctionURL": "https://employeefunctionapp20221213160844.azurewebsites.net/api/EmployeeFunction?code=Bc_QXEgURHtL352LoP8iWRnPhrh6k9452Vxx9OzRAzlKAzFuH7xhmA=="
}

Note: the URL is new because I have created a new Resources in Azure as before.

Create a new class: AppSettings.cs and and add the properties that matches your configuration file as follow:

namespace EmployeeWebApplicationT
{
public class AppSettings
{
public string AzureFunctionURL { get; set; }
}
}

Open the Programs.cs, add the following code for Configure AppSettings:

// Add this for configuration.
builder.Services.AddOptions();
builder.Services.Configure<AppSettings>(
builder.Configuration.GetSection("AppSettings"));

In .NET 6 we haven’t Startup.cs file and that is because we added the above to Program file.

The whole Program.cs file is as follow:

using EmployeeWebApplicationT;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
// Add this for configuration.
builder.Services.AddOptions();
builder.Services.Configure<AppSettings>(
builder.Configuration.GetSection("AppSettings"));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();

create a new C# Class for Employee enitiy class and copy paste the following code:

namespace EmployeeWebApplicationT
{
public class Employee
{
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
}
}

We need install two packages: Microsoft.AspNet.WebApi and Newtonsoft.Json. we can do that via Visual Studio NuGet Package Manager.

We need these package in file : IndexModel (under Pages: index-cshtml.cs)

Open  IndexModel (under Pages: index-cshtml.cs)  modify the constructor like the following:

public class IndexModel : PageModel
{
private AppSettings AppSettings { get; set; }
public IndexModel(IOptions<AppSettings> settings)
{
AppSettings = settings.Value;
}
....
}

In IndexModel (under Pages: index-cshtml.cs) create SerializeJsonIntoStream function with following code:

public static void SerializeJsonIntoStream(object value, Stream stream)
{
using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true))
using (var jtw = new JsonTextWriter(sw) { Formatting = Newtonsoft.Json.Formatting.None })
{
var js = new JsonSerializer();
js.Serialize(jtw, value);
jtw.Flush();
}
}
In this code we create a StreamWriter using one of its overloads:

We first pass the stream to write to. We create a new UTF8Encoding instance passing false to its constructor to deal with UTF-8.

We pass the buffer default buffer size as shown in the StreamWriter source code.
We finally use a boolean to inform the StreamWriter that we don’t want it to become the owner of the stream in the parameter and that we will clean up resources ourselves.

Next Create the HttpContent in the  file IndexModel (under Pages: index-cshtml.cs)

private static HttpContent CreateHttpContent(object content)
{
HttpContent httpContent = null;
if (content != null)
{
var ms = new MemoryStream();
SerializeJsonIntoStream(content, ms);
ms.Seek(0, SeekOrigin.Begin);
httpContent = new StreamContent(ms);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
return httpContent;
}

As you can see, we serialize the content into the stream and return the HttpContent instance to the caller.

Finally, we just need to post the data to the API with a code relatively similar to the classical one.

public async Task<IActionResult> OnPostAsync(string employeeID)
{
var Url = AppSettings.AzureFunctionURL;
dynamic content = new { employeeId = employeeID };
CancellationToken cancellationToken;
using (var client = new HttpClient())
using (var request = new HttpRequestMessage(HttpMethod.Post, Url))
using (var httpContent = CreateHttpContent(content))
{
request.Content = httpContent;
//using (var response = await client
// .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
// .ConfigureAwait(false))
using (var response = await client
.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false))
{
var resualtList = response.Content.ReadAsAsync<List<Employee>>();
ViewData["Employee"] = resualtList.Result;
return Page();
}
}
}

In Index.cshtml (under Pages: index-cshtml) replace the current html code with following:

<div class="row">
<div class="col-md-12">
<hr />
@{
List<Employee> lst = ViewData["Employee"] as List<Employee>;
if (lst != null)
{
foreach (var item in lst)
{
<p>@item.EmployeeName </p>
}
}
}
<hr />
<form method="post">
<label for="firstName">Employee Id</label>
<input type="text" id="employeeID" name="employeeID" placeholder="Employee Id" />
<input type="submit" />
</form>
</div>
</div>

Test WebApplication to consume the FuctionApp

In the Visual Studio press to F5 to start WebApp:

how-to-consume-azurefunction-16.png
Start Browser via WebApp

Write  any number in the field “Employed id” and click submit query button.

how-to-consume-azurefunction-17.png
Putting number 4 as Employee id

The Output is list of employed that we have created locally which is shown as bellow:

how-to-consume-azurefunction-18.png
Output is list of employees and test is succeed

OK Test is working and we could consume our Azure Functions which is deployed in Azure App Service via Web Application from local.

The Source code of Web Application  can be found in my Github

Clean up resources

In the preceding steps, we have created Azure resources in a resource group EmployeeFunctionApp_RSC

  1. From your Web App’s Overview page in the Azure portal, select theEmployeeFunctionApp_RSC
  2. On the resource group page, make sure that the listed resources are the ones you want to delete.
  3. Select Delete, type EmployeeFunctionApp_RSC
     in the text box, and then select Delete.

Conclusion

In this post I have created a Azure Function App and deployed it to Azure App Service. Saved URL for this Function App in the Azure together with App key and tested it.

Then I have created a ASP.NET Core Web Application  in Visual studio and  added code and configured with Azure Function App’s URL and then consumed it by testing locally via this Web App.

In next post I shall explain  Azure container registry

This post is part of “Azure step by step 

Back to home page