DEV Community

Cover image for Serverless Computing with .NET Core and Azure Functions
Paulo Torres
Paulo Torres

Posted on

Serverless Computing with .NET Core and Azure Functions

Serverless computing has revolutionized the way developers build and deploy applications by abstracting away the infrastructure management details. In the .NET ecosystem, Azure Functions provides a powerful platform for building serverless applications with .NET Core. This article explores advanced techniques for developing serverless solutions using Azure Functions, complete with real-world examples and best practices.

Introduction to Serverless Computing

Serverless computing allows developers to focus on writing code without worrying about server provisioning, scaling, or management. With serverless architectures, developers can deploy functions—small, discrete units of work—that scale automatically in response to demand. This paradigm shift enables cost-effective, efficient, and scalable application development.

Setting Up Azure Functions with .NET Core

Step 1: Create an Azure Function App

To start building serverless applications, create an Azure Function App:

  1. Azure Portal: Navigate to the Azure Portal and create a new Function App. Choose your preferred region, resource group, and configure the app to use .NET Core.

  2. Visual Studio: Alternatively, you can create a Function App project in Visual Studio by selecting the "Azure Functions" template and choosing ".NET Core" as the runtime stack.

Step 2: Define a Function

Azure Functions supports various triggers, including HTTP, Timer, Blob Storage, and more. In this example, we will create an HTTP-triggered function.

Function Definition

using System.IO;
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;

public static class MyFunction
{
    [FunctionName("MyFunction")]
    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;

        return name != null
            ? (ActionResult)new OkObjectResult($"Hello, {name}")
            : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Deploying the Function

Using Visual Studio

  1. Right-click on the Function App project and select "Publish."
  2. Choose "Azure" and select the existing Function App created in the Azure portal.
  3. Publish the function to Azure.

Using Azure CLI

Alternatively, you can use the Azure CLI to deploy your Function App:

func azure functionapp publish <YourFunctionAppName>
Enter fullscreen mode Exit fullscreen mode

Real-World Example: Image Processing Pipeline

Scenario

Consider a scenario where an e-commerce platform needs to process images uploaded by users. The images must be resized, watermarked, and stored in Azure Blob Storage.

Implementing the Solution

Image Upload Trigger

Create a Blob Storage-triggered function to process uploaded images:

public static class ImageProcessor
{
    [FunctionName("ImageProcessor")]
    public static async Task Run(
        [BlobTrigger("images/{name}", Connection = "AzureWebJobsStorage")] Stream image,
        string name,
        ILogger log)
    {
        // Process image: resize, watermark, etc.
        // Save processed image to Blob Storage
        log.LogInformation($"Processed image: {name}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Timer Trigger for Scheduled Tasks

In addition to image processing, suppose you need to generate daily reports. Use a Timer Trigger for scheduled tasks:

public static class DailyReportGenerator
{
    [FunctionName("DailyReportGenerator")]
    public static void Run([TimerTrigger("0 0 0 * * *")] TimerInfo myTimer, ILogger log)
    {
        log.LogInformation($"Generating daily report at: {DateTime.Now}");
        // Generate and store report
    }
}
Enter fullscreen mode Exit fullscreen mode

Advanced Topics in Azure Functions

Dependency Injection

Azure Functions support dependency injection, allowing you to manage dependencies in a structured manner.

Example

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddSingleton<IMyService, MyService>();
    }
}

public class MyFunction
{
    private readonly IMyService _myService;

    public MyFunction(IMyService myService)
    {
        _myService = myService;
    }

    [FunctionName("MyFunction")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        return new OkObjectResult(_myService.PerformOperation());
    }
}
Enter fullscreen mode Exit fullscreen mode

Monitoring and Scaling

Monitoring with Application Insights

Azure Functions integrate with Application Insights for monitoring and diagnostics. You can track performance, log custom events, and analyze telemetry data.

Auto-Scaling

Azure Functions automatically scale based on demand. You can configure scaling settings through the Azure portal, ensuring your application handles traffic spikes efficiently.

Best Practices

  1. Function Granularity: Keep functions small and focused on a single task. This improves maintainability and scalability.
  2. Idempotency: Ensure functions are idempotent, meaning they can handle repeated invocations without unintended side effects.
  3. Error Handling: Implement robust error handling and logging to diagnose issues quickly.
  4. Security: Secure function endpoints using Azure Active Directory, API keys, or other authentication mechanisms.
  5. Cost Management: Monitor and manage costs by optimizing function execution time and resource consumption.

Conclusion

Serverless computing with .NET Core and Azure Functions offers a versatile and scalable approach to application development. By leveraging the capabilities of Azure Functions, developers can build robust, scalable, and cost-effective solutions with ease. Whether you're processing images, generating reports, or handling user requests, Azure Functions provides the tools needed to implement advanced serverless architectures. Embrace serverless computing to streamline your development process and unlock new possibilities in the cloud.

Top comments (0)