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
- Create new project → "Azure Functions"
- Choose ".NET 6 (Long Term Support)"
- Select "Http trigger" template
- 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
- Install "Azure Functions" extension
- Sign in to Azure
- Click "Deploy to Function App"
- 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
| Concept | Description |
|---|---|
| Function Name | "HttpExample" - endpoint path |
| Trigger | HTTP - responds to web requests |
| Auth Level | Function - requires API key |
| Parameters | Query 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
- Learn about Hosting Plans Overview
- Explore Timer Trigger for Scheduled Tasks
- Learn about Data Processing with Blob Triggers
Azure Integration Hub - Beginner Level