Create And Consume Azure Function From ASP.NET Core

Introduction

Azure Functions lets you execute your code in a serverless environment without having to first create a VM or publish a web application.

In this article, you learn how create an Azure function by using Visual Studio 2017 tools. You then publish the function code to Azure. Then you call this function by using ASP.NET Core Web application.

Create Azure Function

 
To create an Azure function through Visual Studio 2017, in visual studio on the File menu, select New > Project.
 
Create And Consume Azure Function From ASP.NET Core

Select Cloud > Azure Functions

Create And Consume Azure Function From ASP.NET Core

Create a new function named HR Leave Request List Function. 

Select Http Trigger, for storage account select None, and for Access rights select Function.

In Function under Access rights, you're required to present the function key in requests to access your function endpoint.

Create And Consume Azure Function From ASP.NET Core

In this article, I need to create a simple function that returns a list of leave requests. So first I need to create entity class for leave request.

Right click on project and select Add > Class

Create And Consume Azure Function From ASP.NET Core

Rename the class as LeaveRequest. Add the following code to LeaveRequest Class.

  1. public class LeaveRequest  
  2.     {  
  3.         [JsonProperty(PropertyName = "employeeId")]  
  4.         public string EmployeeId { getset; }  
  5.         public string Name { getset; }  
  6.         public DateTime From { getset; }  
  7.         public DateTime To { getset; }  
  8.     }  

In function class add the following code:

  1. public static class HrLeaveRequest  
  2.     {  
  3.         [FunctionName("LeaveRequestList")]  
  4.         public static async Task<IActionResult> Run(  
  5.             [HttpTrigger(AuthorizationLevel.Function, "get""post", Route = null)] HttpRequest req )  
  6.         {  
  7.   
  8.             List<LeaveRequest> lst = null;  
  9.             string EmployeeId = string.Empty;  
  10.   
  11.             string requestBody = await new StreamReader(req.Body).ReadToEndAsync();  
  12.             dynamic data = JsonConvert.DeserializeObject(requestBody);  
  13.             EmployeeId = data?.employeeId;  
  14.   
  15.   
  16.             if(EmployeeId != null)  
  17.             {  
  18.                lst = new List<LeaveRequest>();  
  19.                 for (int i = 1; i < 4; i++)  
  20.                 {  
  21.                     lst.Add(new LeaveRequest() { EmployeeId = "10", Name = $"Employee {i}", From= DateTime.Now.AddDays(-i -1), To = DateTime.Now.AddDays(-i)});  
  22.                 }  
  23.   
  24.                 return (ActionResult)new OkObjectResult(lst);  
  25.             }  
  26.   
  27.             return  new BadRequestObjectResult("Please pass a employee Id in the request body");  
  28.         }  
  29.     }  

The above code returns a list of leave requests as static data for demo purposes.

Our function is ready now to test locally. From Debug select Start Debugging.

Create And Consume Azure Function From ASP.NET Core
 
Create And Consume Azure Function From ASP.NET Core
 
Create And Consume Azure Function From ASP.NET Core

Copy the function URL from console application, and from Postman tool paste the URL as the following:

Create And Consume Azure Function From ASP.NET Core

Next, you need to deploy this function to Azure. Right click on project and select Publish.

 Create And Consume Azure Function From ASP.NET Core

Select Create New. And fill in all required fields.

Create And Consume Azure Function From ASP.NET Core
 
Create And Consume Azure Function From ASP.NET Core

Then click On Create Button.

After publishing the function, we need to obtain keys. Keys are stored as part of your function app in Azure. To view your keys, navigate to one of your HTTP-triggered functions in the Azure portal and select Manage.
 
Create And Consume Azure Function From ASP.NET Core
 
Most HTTP trigger templates require an API key in the request. So, your HTTP request normally looks like the following URL:
 
Copy
 
https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?code=<API_KEY> 

To test function after publishing, open the postman tool and past the new URL with Code and test.

https://hrleaverequestlistfunction20190414030124.azurewebsites.net/api/LeaveRequestList?code=<API_Key>

Create And Consume Azure Function From ASP.NET Core
 

Create ASP.NET Core Web App to call Azure function

In Visual Studio on the File menu, select New > Project.

Select Web > ASP.NET Core Web Application.
 
Create And Consume Azure Function From ASP.NET Core
 
Create And Consume Azure Function From ASP.NET Core

Rename the project and click OK.

In appsettings.json file add the Azure Function URL with Code:

  1. "AppSettings": {  
  2.   "AzureFunctionURL""https://[AppName].azurewebsites.net/api/[FunctionName]?code=<API_Key>"  
  3. }  

 Next, create a new C# Class, and add the properties that matches your configuration file:

  1. public class AppSettings  
  2.  {  
  3.      public string AzureFunctionURL { getset; }  
  4.  }  

Open Startup.cs, add the code for Configure AppSettings. 

  1. public void ConfigureServices(IServiceCollection services)  
  2.    {  
  3.          …  
  4.   
  5.   services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));  
  6.   
  7.          …  
  8.    }  

Whenever you use the type AppSettings in your code, it will return an instance of Configuration.GetSection("AppSettings")

Next, create a new C# Class for LeaveRequest enitiy class.
  1. public class LeaveRequest  
  2.     {  
  3.         public string EmployeeId { getset; }  
  4.         public string Name { getset; }  
  5.         public DateTime From { getset; }  
  6.         public DateTime To { getset; }  
  7.     }  

Finally, in your IndexModel, modify the constructor like this,

  1. public class IndexModel : PageModel  
  2.     {  
  3.         private AppSettings AppSettings { getset; }  
  4.   
  5.         public IndexModel(IOptions<AppSettings> settings)  
  6.         {  
  7.             AppSettings = settings.Value;  
  8.         }  
  9. …  
  10. }  
In IndexModel create SerializeJsonIntoStream function,
  1. public static void SerializeJsonIntoStream(object value, Stream stream)  
  2.     {  
  3.         using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true))  
  4.         using (var jtw = new JsonTextWriter(sw) { Formatting = Formatting.None })  
  5.         {  
  6.             var js = new JsonSerializer();  
  7.             js.Serialize(jtw, value);  
  8.             jtw.Flush();  
  9.         }  
  10.     }  
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.

  1. private static HttpContent CreateHttpContent(object content)  
  2.       {  
  3.           HttpContent httpContent = null;  
  4.   
  5.           if (content != null)  
  6.           {  
  7.               var ms = new MemoryStream();  
  8.               SerializeJsonIntoStream(content, ms);  
  9.               ms.Seek(0, SeekOrigin.Begin);  
  10.               httpContent = new StreamContent(ms);  
  11.               httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");  
  12.           }  
  13.   
  14.           return httpContent;  
  15.       }  

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.

  1. public async Task<IActionResult> OnPostAsync(string employeeID)  
  2. {  
  3.     var Url = AppSettings.AzureFunctionURL ;  
  4.   
  5.     dynamic content = new { employeeId = employeeID };  
  6.   
  7.     CancellationToken cancellationToken;  
  8.   
  9.   
  10.     using (var client = new HttpClient())  
  11.     using (var request = new HttpRequestMessage(HttpMethod.Post, Url ))  
  12.     using (var httpContent = CreateHttpContent(content))  
  13.     {  
  14.         request.Content = httpContent;  
  15.   
  16.         using (var response = await client  
  17.             .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken)  
  18.             .ConfigureAwait(false))  
  19.         {  
  20.   
  21.             var resualtList = response.Content.ReadAsAsync<List<LeaveRequest>>();  
  22.   
  23.             ViewData["LeaveRequest"] = resualtList.Result;  
  24.   
  25.             return Page();  
  26.         }  
  27.     }  
  28.   
  29. }  

In Index.cshtml replace the current html code with following:

  1. <div class="row">  
  2.     <div class="col-md-12">  
  3.         <hr />  
  4.         @{  
  5.             List<LeaveRequest> lst = ViewData["LeaveRequest"as List<LeaveRequest>;  
  6.   
  7.             if (lst != null)  
  8.             {  
  9.                 foreach (var item in lst)  
  10.                 {  
  11.                     <p>@item.Name - @item.From.ToShortDateString() - @item.To.ToShortDateString()</p>  
  12.                 }  
  13.             }  
  14.         }  
  15.         <hr />  
  16.         <form method="post">  
  17.   
  18.             <label for="firstName">Employee Id</label>  
  19.             <input type="text" id="employeeID" name="employeeID" placeholder="Employee Id" />  
  20.             <input type="submit" />  
  21.         </form>  
  22.     </div> 
  23. </div>  

Run the web by press on F5.

Create And Consume Azure Function From ASP.NET Core

Put any number and click submit query button. 

Create And Consume Azure Function From ASP.NET Core

Congratulations. It's working!