Your First HTTP Function in Azure Functions

Overview

This hands-on tutorial walks you through creating and deploying your first Azure Function - a simple HTTP-triggered function that responds to web requests. By the end of this guide, you'll have a working API endpoint running in Azure that you can call from anywhere in the world.

What You'll Learn

  • Creating a new Azure Functions project
  • Writing an HTTP-triggered function
  • Running and testing your function locally
  • Deploying your function to Azure
  • Testing the deployed function

Prerequisites

Before starting, ensure you have the following tools installed on your machine:

  • .NET 6.0 or later - The Azure Functions runtime
  • Azure Functions Core Tools - For local development and deployment
  • VS Code (recommended) or Visual Studio - For writing and deploying code

Prerequisites

  • .NET 6.0 or later installed
  • Azure Functions Core Tools
  • VS Code (recommended) or Visual Studio

Step 1: Create Project

Using Terminal

# Create new function app
func init MyFunctionApp --worker-runtime dotnet

cd MyFunctionApp

# Add HTTP function
func new --name HttpExample --template "HTTP trigger" --authlevel function

Using Visual Studio

  1. Create new project → "Azure Functions"
  2. Choose ".NET 6 (Long Term Support)"
  3. Select "Http trigger" template
  4. Name it "HttpExample"

Step 2: Run Locally

func start

Your function runs at: http://localhost:7071/api/HttpExample

Test with curl

# Without query param
curl http://localhost:7071/api/HttpExample

# With name param
curl "http://localhost:7071/api/HttpExample?name=World"

Code Explained

using System.IO;
using Microsoft.Azure.Functions.Worker;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

public class HttpExample
{
    private readonly ILogger<HttpExample> _logger;

    public HttpExample(ILogger<HttpExample> logger)
    {
        _logger = logger;
    }

    [Function("HttpExample")]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
    {
        _logger.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 ??= data?.name;

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

Step 3: Deploy to Azure

Option 1: VS Code

  1. Install "Azure Functions" extension
  2. Sign in to Azure
  3. Click "Deploy to Function App"
  4. Follow prompts

Option 2: CLI

# Create resource group
az group create --name my-rg --location eastus

# Create storage account (required)
az storage account create --name mystorage123 --resource-group my-rg --sku Standard_LRS

# Create function app
az functionapp create \
  --resource-group my-rg \
  --name my-function-app \
  --storage-account mystorage123 \
  --consumption-plan-location eastus \
  --runtime dotnet

# Deploy
func azure functionapp publish my-function-app

Test Deployed Function

https://my-function-app.azurewebsites.net/api/HttpExample?name=Azure

Returns: Hello, Azure


Key Concepts

ConceptDescription
Function Name"HttpExample" - endpoint path
TriggerHTTP - responds to web requests
Auth LevelFunction - requires API key
ParametersQuery string or request body

Real-Time Scenarios

Scenario 1: Processing Order Data from API Request

A common pattern is receiving order data via HTTP and processing it:

public class OrderFunction
{
    [Function("ProcessOrder")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req)
    {
        // Read order from request body
        var orderBody = await new StreamReader(req.Body).ReadToEndAsync();
        var order = JsonSerializer.Deserialize<Order>(orderBody);
        
        // Validate order
        if (order == null || string.IsNullOrEmpty(order.CustomerId))
            return new BadRequestObjectResult("Invalid order data");
        
        // Process order (save to database, queue for processing, etc.)
        await _orderService.ProcessOrderAsync(order);
        
        return new OkObjectResult(new { 
            OrderId = order.Id, 
            Status = "Processing" 
        });
    }
}

Scenario 2: Webhook Handler for External Events

Handle webhooks from payment gateways, CRMs, or other services:

public class WebhookFunction
{
    [Function("HandlePaymentWebhook")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
        ILogger log)
    {
        // Verify webhook signature (security!)
        var signature = req.Headers["X-Webhook-Signature"].FirstOrDefault();
        if (!ValidateSignature(signature, await req.ReadAsStringAsync()))
            return new UnauthorizedResult();
        
        // Process webhook payload
        var payload = await req.ReadAsStringAsync();
        var paymentEvent = JsonSerializer.Deserialize<PaymentEvent>(payload);
        
        log.LogInformation("Received payment event: {EventId}", paymentEvent.EventId);
        
        // Update order status in database
        await _paymentService.ProcessPaymentEventAsync(paymentEvent);
        
        return new OkResult();
    }
}

Scenario 3: API Backend with APIM Integration

Your function can be called from Azure API Management:

// Called by APIM - receives headers with subscription key
[Function("GetProductCatalog")]
public async Task<IActionResult> GetProducts(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
    // Get APIM subscription info from headers
    var subscriptionKey = req.Headers["Ocp-Apim-Subscription-Key"].FirstOrDefault();
    
    // Parse query parameters
    var category = req.Query["category"];
    var page = int.TryParse(req.Query["page"], out var p) ? p : 1;
    
    // Get products from database
    var products = await _productService.GetProductsAsync(category, page);
    
    return new OkObjectResult(new
    {
        Products = products,
        Page = page,
        Total = products.Count
    });
}

Scenario 4: Data Validation & Transformation

Process and transform incoming data before storing:

public class TransformFunction
{
    [Function("TransformData")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
        [Queue("output-queue")] ICollector<string> outputQueue)
    {
        var rawData = await req.ReadAsStringAsync();
        
        // Parse and validate
        var input = JsonSerializer.Deserialize<InputData>(rawData);
        if (!Validate(input))
            return new BadRequestObjectResult("Invalid data format");
        
        // Transform to output format
        var output = TransformToOutput(input);
        
        // Send to queue for further processing
        outputQueue.Add(JsonSerializer.Serialize(output));
        
        return new OkObjectResult(new { Status = "Processed", Id = output.Id });
    }
}

Scenario 5: Integration with Azure Services

Functions work seamlessly with other Azure services:

public class FileProcessingFunction
{
    [Function("ProcessUploadedFile")]
    public async Task Run(
        [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
        [Blob("uploads")] BlobContainerClient container,
        ILogger log)
    {
        // Get file from request
        var file = req.Form.Files.FirstOrDefault();
        if (file == null)
            return;
        
        // Upload to Blob Storage
        var blobClient = container.GetBlobClient(file.FileName);
        using var stream = file.OpenReadStream();
        await blobClient.UploadAsync(stream, overwrite: true);
        
        log.LogInformation("File uploaded: {FileName}", file.FileName);
    }
}

Testing Your Function

Using Postman/Insomnia

# POST with JSON body
curl -X POST "http://localhost:7071/api/HttpExample" \
  -H "Content-Type: application/json" \
  -d '{"name": "Customer"}'

# With function key (if AuthorizationLevel.Function)
curl "http://localhost:7071/api/HttpExample?name=Test&code=YOUR_FUNCTION_KEY"

Next Steps


Azure Integration Hub - Beginner Level