mirror of
https://github.com/github/awesome-copilot.git
synced 2026-04-11 02:35:55 +00:00
* feat: add azure-functions-csharp.instructions.md Added guidelines and best practices for building Azure Functions in C# using the isolated worker model. * feat: add azure-durable-functions-csharp.instructions.md Added guidelines and best practices for building Azure Durable Functions in C# using the isolated worker model. * docs: add config & testing sections to durable functions instructions Added detailed configuration and testing guidelines for Azure Durable Functions in C#. * Fix capitalization in applyTo path for local.settings.json Changed Local.settings.json to local.settings.json in the applyTo directive to match the actual filename used in Azure Functions projects. * update through npm build
9.2 KiB
9.2 KiB
description, applyTo
| description | applyTo |
|---|---|
| Guidelines and best practices for building Azure Functions in C# using the isolated worker model | **/*.cs, **/host.json, **/local.settings.json, **/*.csproj |
Azure Functions C# Development
General Instructions
- Always use the isolated worker model (not the legacy in-process model) for all new Azure Functions projects targeting .NET 6 or later.
- Use
FunctionsApplication.CreateBuilder(args)orHostBuilderinProgram.csfor host setup and dependency injection. - Decorate function methods with
[Function("FunctionName")]and use strongly typed trigger and binding attributes. - Keep function methods focused — each function should do one thing and delegate business logic to injected services.
- Never put business logic directly inside the function method body; extract it into testable service classes registered via DI.
- Use
ILogger<T>injected through the constructor, notILoggerpassed as a function parameter, for consistent structured logging. - Always use
async/awaitfor all I/O-bound operations; never block with.Resultor.Wait(). - Prefer
CancellationTokenparameters where supported to enable graceful shutdown.
Project Structure and Setup
- Use the
Microsoft.Azure.Functions.WorkerandMicrosoft.Azure.Functions.Worker.Extensions.*NuGet packages. - Register services in
Program.csusingbuilder.Services.Add*extension methods for clean dependency injection. - Group related functions into separate classes by domain concern, not by trigger type.
- Store configuration in
local.settings.jsonfor local development; use Azure App Configuration or Application Settings for deployed environments. - Never hardcode connection strings or secrets in code; always read from
IConfigurationor environment variables. - Use Key Vault references (
@Microsoft.KeyVault(SecretUri=...)) in App Settings for secrets in deployed environments. - Use
Managed Identity(DefaultAzureCredential) for authenticating to Azure services — avoid connection strings with keys wherever possible. - Keep
host.jsontuned per trigger type: configuremaxConcurrentCalls,batchSize, and retry policies at the host level.
Triggers
- HttpTrigger: Use
AuthorizationLevel.Functionor higher for production endpoints; reserveAuthorizationLevel.Anonymousonly for public-facing APIs with explicit justification. Use ASP.NET Core integration (UseMiddleware,IActionResultreturns) when using the ASP.NET Core integration model. - TimerTrigger: Use NCRONTAB expressions (
"0 */5 * * * *") for schedules; avoidRunOnStartup = truein production as it executes immediately on every cold start. - QueueTrigger / ServiceBusTrigger: Configure
MaxConcurrentCalls, dead-letter policies, andMaxDeliveryCountinhost.jsonand Azure portal; handleServiceBusReceivedMessagedirectly for advanced message control (complete, abandon, dead-letter). - BlobTrigger: Prefer Event Grid-based blob triggers (
Microsoft.Azure.Functions.Worker.Extensions.EventGrid) over polling-based blob triggers for lower latency and reduced storage transaction costs. - EventHubTrigger: Set
cardinalitytomanyfor batch processing; useEventData[]orstring[]parameter types for batch mode; always checkpoint using theEventHubTriggerAttribute's built-in checkpointing. - CosmosDBTrigger: Use the change feed trigger for event-driven processing of Cosmos DB changes; set
LeaseContainerNameand manage lease containers separately from data containers.
Input and Output Bindings
- Use input bindings to read data declaratively rather than using SDKs directly inside function bodies where the binding covers the use case.
- For multiple output bindings, define a custom return type with properties annotated with the appropriate output binding attributes (e.g.,
[QueueOutput],[BlobOutput],[HttpResult]). - Use
[BlobInput]and[BlobOutput]for blob read/write; preferStreamoverbyte[]for large blobs to avoid memory pressure. - Use
[CosmosDBInput]for point reads and simple queries; for complex queries, injectCosmosClientvia DI withManaged Identity. - Use
[ServiceBusOutput]for single-message sends; injectServiceBusSendervia DI for batching or advanced send scenarios. - Avoid mixing SDK clients obtained via DI with binding-based I/O for the same resource — choose one pattern per resource to maintain consistency.
Dependency Injection and Configuration
- Register all external clients (e.g.,
BlobServiceClient,ServiceBusClient,CosmosClient) as singletons usingservices.AddAzureClients()from theAzure.Extensions.AspNetCore.Configuration.Secretspackage withDefaultAzureCredential. - Use
IOptions<T>orIOptionsMonitor<T>for strongly typed configuration sections. - Avoid using
staticstate in functions; all shared state should flow through DI-registered services. - Register
HttpClientinstances viaIHttpClientFactoryto manage connection pooling and avoid socket exhaustion.
Error Handling and Retry
- Configure built-in retry policies in
host.jsonusing"retry"withfixedDelayorexponentialBackoffstrategy for trigger-level retries. - For transient fault handling at the code level, use
Microsoft.Extensions.Http.Resilienceor Polly v8 (ResiliencePipeline) with retry, circuit breaker, and timeout strategies. - Always catch specific exceptions and log them with structured context (e.g., correlation ID, input identifier) before re-throwing or dead-lettering.
- Use dead-letter queues for messages that fail after all retries; never silently swallow exceptions in function handlers.
- For HTTP triggers, return appropriate
IActionResulttypes (BadRequestObjectResult,NotFoundObjectResult) rather than throwing exceptions for expected error conditions.
Observability and Logging
- Use
ILogger<T>with structured log properties:_logger.LogInformation("Processing message {MessageId}", messageId). - Configure Application Insights via
builder.Services.AddApplicationInsightsTelemetryWorkerService()andbuilder.Logging.AddApplicationInsights()inProgram.cs. - Use
TelemetryClientfor custom events, metrics, and dependency tracking beyond what is automatically collected. - Set appropriate log levels in
host.jsonunder"logging"to avoid excessive telemetry costs in production. - Use
ActivityandActivitySourcefromSystem.Diagnosticsfor distributed tracing context propagation between functions and downstream services. - Avoid logging sensitive data (PII, secrets, connection strings) in any log statement.
Performance and Scalability
- Keep function startup time minimal: defer expensive initialization to lazy-loaded singletons, not the function constructor.
- Use the Consumption plan for event-driven, unpredictable workloads; use Premium or Dedicated plans for low-latency, high-throughput, or VNet-integrated scenarios.
- For CPU-intensive work, offload to a background
Taskor use Durable Functions rather than blocking the function host thread. - Batch operations where possible: process
IEnumerable<EventData>orServiceBusReceivedMessage[]arrays in a single function invocation rather than one message at a time. - Set
FUNCTIONS_WORKER_PROCESS_COUNTandmaxConcurrentCallsappropriately for the hosting plan and expected throughput. - Enable
WEBSITE_RUN_FROM_PACKAGE=1in App Settings for faster cold starts by running directly from a deployment package.
Security
- Always validate and sanitize HTTP trigger inputs before processing; use FluentValidation or Data Annotations.
- Use
AuthorizationLevel.Functionwith function keys stored in Key Vault for internal API-to-API calls. - Integrate Azure API Management (APIM) in front of HTTP-triggered functions for public-facing APIs to handle auth, rate limiting, and routing.
- Restrict inbound access using App Service networking features (IP restrictions, Private Endpoints) for sensitive functions.
- Never log request bodies containing PII or secrets.
Testing
- Unit-test service classes independently of the function host using standard xUnit/NUnit with mocked dependencies.
- Integration-test functions using
Azurite(local Azure Storage emulator) andTestServeror the Azure Functions Core Tools. - Use the
Microsoft.Azure.Functions.Worker.Testinghelpers where available to construct mockFunctionContextinstances. - Avoid testing the trigger plumbing itself; focus tests on the business logic extracted into services.
Existing Code Review Guidance
- If a project uses the legacy in-process model (
FunctionsStartup,IWebJobsStartup), suggest migrating to the isolated worker model and provide the migration path viadotnet-isolated-process-guide. - If hardcoded connection strings or storage account keys are found in code or config files, flag them and suggest replacing with
DefaultAzureCredentialand Key Vault references. - If
RunOnStartup = trueis set on aTimerTriggerin a production app, flag it as a risk and suggest using deployment slots or feature flags instead. - If
async voidis used in any function, flag it immediately — useasync Taskinstead. - If retry logic is implemented manually with
Thread.SleeporTask.Delayinside a function, suggest replacing with host-level retry policies or Polly resilience pipelines.