Azure Deploy Example - C# .NET
Today we’ll deploy a tiny C# .NET function to Azure Functions on the Linux Consumption plan. It’s a single HTTP endpoint that returns “Hello world.”
Architecture
Layer | Component | Responsibility | Files / Packages | Notes |
---|---|---|---|---|
Client | CLI (curl) / Postman / HTTPie | Send HTTP requests to test the API | — | Use curl in examples; GUI tools like Postman also work. |
API (Functions) | Azure Functions (HTTP trigger, isolated) | Expose REST endpoints under /api (e.g., /api/test ) | Functions/Test.cs (or Test.cs ), Microsoft.Azure.Functions.Worker | Azure Functions v4 on Linux Consumption, .NET 8 isolated model. |
Handler | [Function("Test")] method | Handle GET and return JSON | Functions/Test.cs (or Test.cs ) | Route Route = "test" → final path /api/test ; AuthorizationLevel.Anonymous for quick tests. |
DTO / Payload | Simple C# object { message: string } | Define response shape | Inline anonymous type or small record/class | Keep payloads explicit; expand to request DTOs as you add POST/PUT later. |
Response Helpers | WriteAsJsonAsync(...) | Consistent JSON responses + content type | Microsoft.Azure.Functions.Worker.Http | Prefer async APIs (no sync writes). |
Error Handling | Try/catch + ctx.GetLogger().LogError(...) | Return proper HTTP status codes on failures | Functions/Test.cs | Return 500 on unhandled errors; log via the Functions logger. |
Config | Host + local settings | Runtime & local dev configuration | host.json , local.settings.json | /api prefix comes from Functions defaults; secrets in Azure App Settings in the portal. |
Build Tooling | .NET SDK + Func Core Tools | Build, run locally, publish to Azure | .csproj , dotnet , Azure Functions Core Tools (func ) | dotnet build → func start ; func azure functionapp publish <app> . |
Cloud Resources | Function App + Storage Account | Host the function; triggers/state/checkpoints | Created via az functionapp create , az storage account create | Storage account name: 3–24 chars, lowercase + digits, globally unique. |
Observability | App Insights (optional) | Centralized logs/metrics/traces | Enable in Function App → Application Insights | Super handy once you add more routes or diagnose issues. |
Security/Auth | Anonymous (demo) | Public endpoint for learning | AuthorizationLevel.Anonymous | For real use, switch to Function /Admin or enable Entra ID (Easy Auth). |
Platform | .NET 8 (isolated worker) | Language/runtime version | --runtime dotnet-isolated , --runtime-version 8 | Stick to LTS for stability and Functions compatibility. |
Dependencies
- Azure Functions Core Tools v4
- Azure CLI
- (New users) Create free Azure account or credits
- Dotnet SDK v8
If you use VSCode, you may want following extensions:
- C# (ms-dotnettools.csharp) or C# Dev Kit (ms-dotnettools.csdevkit)
- Azure Functions (ms-azuretools.vscode-azurefunctions)
- For Azure sign-in: Azure Account (ms-vscode.azure-account)
Login to Azure and select subscription
We need to login to Azure. Use the default subscription that was created when free account was created.
az login
az account list -o table
az account set --subscription "<Your-Subscription-Name-or-ID>"
Register namespaces
We need a couple namespaces enabled for the application, so enable them if not already. If state is “registering”, wait a couple minutes and run show command again.
az provider show --namespace Microsoft.Storage --query "registrationState"
az provider show --namespace Microsoft.Web --query "registrationState"
az provider register --namespace Microsoft.Storage
az provider register --namespace Microsoft.Web
Create resource group
Resource group contains all the resources for this project. Choose the location from given list, we use westeurope as an example.
az account list-locations --query "[].name" -o tsv
az group create \
-n azure-deploy-example \
-l westeurope
Create storage account
Functions requires a general-purpose storage account for triggers, logs, and state.
Use Standard_LRS (lowest cost). Storage isn’t “free”, but with small usage and free credits it’s typically zero cost while learning. Naming rules: 3–24 chars, lowercase letters & numbers only, globally unique. So in case the name is taken, choose some other name.
az storage account create \
-n azuredeployecxzxghr0m \
-g azure-deploy-example \
-l westeurope \
--sku Standard_LRS
Create function app
Next we create function application that holds our functions. Application name must be globally unique (becomes <name>.azurewebsites.net).
az functionapp create \
-n azure-deploy-example-dotnet-ecxzxghr0m \
-g azure-deploy-example \
--consumption-plan-location westeurope \
--runtime dotnet-isolated \
--runtime-version 8 \
--functions-version 4 \
--os-type linux \
--storage-account azuredeployecxzxghr0m
Prepare the app
The application is very basic, mostly whatever is coming from scaffold. Application sources are here.
Scaffold the project
Create repository files with func cli tool. We use isolated dotnet, so the process dependencies does not get mixed up.
mkdir dotnet-func && cd dotnet-func
func init . --dotnet-isolated
Create function
Save file to Functions/test.ts
using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespace Company.Function;
public class Test
{
[Function("Test")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "test")]
HttpRequestData req,
FunctionContext ctx)
{
var res = req.CreateResponse(HttpStatusCode.OK);
await res.WriteAsJsonAsync(new { message = "Hello world from dotnet" });
return res;
}
}
Note: we use async + WriteAsJsonAsync
to avoid the “Synchronous operations are disallowed” error
Run locally
Build and run application, and then we can test it with curl, browser or any other similar tool.
dotnet build
func start
# in another terminal window
curl http://localhost:7071/api/test
Publish
This will publish app to production.
dotnet build
func azure functionapp publish azure-deploy-example-ecxzxghr0m
# test in the cloud
curl https://azure-deploy-example-ecxzxghr0m.azurewebsites.net/api/test
Recap
We created a Function App, added a C# .NET HTTP function, tested locally, and published to Azure.