Skip to content

Migrate trigger functions to ConnectorTrigger extension attribute#56

Open
manvkaur wants to merge 5 commits into
mainfrom
manvkaur/connectortrigger
Open

Migrate trigger functions to ConnectorTrigger extension attribute#56
manvkaur wants to merge 5 commits into
mainfrom
manvkaur/connectortrigger

Conversation

@manvkaur
Copy link
Copy Markdown

@manvkaur manvkaur commented Jun 4, 2026

Description

Migrate all trigger functions from the manual HttpTrigger + JSON deserialization pattern to the [ConnectorTrigger] extension attribute from Microsoft.Azure.Functions.Worker.Extensions.Connector. The extension handles HTTP plumbing, payload parsing, and error responses automatically.

Changes

Trigger Migration

  • Office365: OnNewEmail — receives Office365OnNewEmailTriggerPayload, logs email count and operational metadata (Id, ReceivedTime, HasAttachments, Importance)
  • SharePoint: OnNewSharePointItem — receives SharePointOnlineOnNewItemsTriggerPayload, logs item count and additional property count
  • Teams: OnNewChannelMessage — receives TeamsOnNewChannelMessageTriggerPayload, logs message count
  • OneDrive: OnNewOneDriveFiles — receives OneDriveForBusinessOnNewFilesTriggerPayload, logs file name and size
  • Azure Blob: OnBlobUpdated — receives AzureBlobOnUpdatedFilesTriggerPayload
  • Event Hubs: OnNewEvents — receives EventHubsOnNewEventsTriggerPayload
  • Service Bus: OnQueueMessages — receives ServicebusOnGetMessagesFromQueueTriggerPayload
  • Outlook: OnNewOutlookEmail — receives OutlookOnNewEmailTriggerPayload
  • WDATP: OnNewRemediationActivity — receives WdatpOnNewRemediationActivityTriggerPayload
  • Event Grid: OnEventGridResourceEvent — receives raw string payload
  • Azure Queues: OnQueueMessagesAvailable — receives raw string payload
  • Yammer: OnNewYammerMessage — receives raw string payload

Current Pattern

Trigger functions use void return type with typed SDK payload binding. The ConnectorTrigger extension deserializes the webhook JSON into the SDK payload type automatically. Functions log payload metadata for observability. Null-safe payload access (payload?.Body?.Value) ensures graceful handling when the extension passes null or incomplete data.

Tests

  • Rewrote trigger tests for ConnectorTrigger pattern using Mock<ILogger<T>> to verify log output
  • Each trigger has 3 tests: valid payload (asserts count logged), empty payload (asserts zero logged), null payload (asserts graceful handling)
  • All existing HTTP function tests preserved (GetAllTeams, GetChannels, SendEmail, etc.)
  • Removed duplicate OutlookFunctions.cs from test project (upstream merge artifact)

Infrastructure

  • Added Microsoft.Azure.Functions.Worker.Extensions.Connector 0.2.0-alpha package
  • Added OpenTelemetry packages for observability
  • Updated test project TFM to net10.0

Test Results

31 tests passed, 0 failed

Comment thread DirectConnector/Office365Functions.cs Fixed
manvkaur and others added 2 commits June 4, 2026 04:58
Replace HttpTrigger + manual JSON deserialization with ConnectorTrigger
attribute from the Functions Worker Extensions Connector package. The
extension now handles HTTP plumbing, payload parsing, and error handling
automatically.

- Add Microsoft.Azure.Functions.Worker.Extensions.Connector 0.2.0-alpha
- Add OpenTelemetry, Azure Monitor exporter packages
- Add ActivitySource listener for connector SDK tracing in dev mode
- Migrate Office365, SharePoint, Teams, OneDrive, AzureBlob, EventGrid,
  EventHubs, Queues, ServiceBus, Outlook, Wdatp, Yammer trigger functions
- Remove ConnectorTriggerMetadataAttribute POC placeholder

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Rewrite SharePoint, Teams, Office365 trigger tests for void ConnectorTrigger pattern
- Use Mock<ILogger> to verify log output (count of items/messages/emails)
- Test valid payload, empty payload, and null payload for each trigger
- Remove duplicate OutlookFunctions.cs from test project (upstream merge artifact)
- Update test project TFM to net10.0

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@manvkaur manvkaur force-pushed the manvkaur/connectortrigger branch from 0749af4 to 187a4e5 Compare June 4, 2026 12:37
manvkaur and others added 3 commits June 4, 2026 05:40
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
- Update test assertions to match 'Received new email notification' log message
  (CodeQL autofix removed emailCount from logging)
- Update CI workflow dotnet-version from 8.0.x to 10.0.x to match net10.0 TFM

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ip ci]

- Update test assertions to match 'Received new email notification' log message
  (CodeQL autofix removed emailCount from logging)
- Update CI workflow dotnet-version from 8.0.x to 10.0.x to match net10.0 TFM

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@manvkaur manvkaur marked this pull request as ready for review June 4, 2026 13:10
@manvkaur manvkaur requested a review from a team as a code owner June 4, 2026 13:10
Copilot AI review requested due to automatic review settings June 4, 2026 13:10
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates multiple “trigger callback” Azure Functions from an explicit HttpTrigger + manual JSON handling approach to the Microsoft.Azure.Functions.Worker.Extensions.Connector [ConnectorTrigger] binding, and updates the sample app’s runtime/telemetry setup to align with the new trigger model.

Changes:

  • Replaced several connector trigger callback HTTP endpoints with [ConnectorTrigger]-bound functions (typed payloads where available; string otherwise).
  • Updated/rewrote unit tests for migrated triggers to validate logging behavior with Moq<ILogger<T>>.
  • Updated project/CI configuration (TFM upgrade to net10.0) and added OpenTelemetry/Azure Monitor exporter wiring.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
README.md Adds links to related Azure Functions sample repos using the connector trigger extension.
DirectConnector/AzureBlobFunctions.cs Adds OnBlobUpdated [ConnectorTrigger] function.
DirectConnector/AzureEventGridFunctions.cs Adds OnEventGridResourceEvent [ConnectorTrigger] function (raw string payload).
DirectConnector/AzureQueuesFunctions.cs Adds OnQueueMessagesAvailable [ConnectorTrigger] function (raw string payload).
DirectConnector/EventHubsFunctions.cs Adds OnNewEvents [ConnectorTrigger] function.
DirectConnector/Office365Functions.cs Replaces the HTTP trigger callback with OnNewEmail [ConnectorTrigger] and logs email metadata.
DirectConnector/OneDriveFunctions.cs Removes the prior HTTP trigger callback handler and adds OnNewOneDriveFiles [ConnectorTrigger].
DirectConnector/OutlookFunctions.cs Adds OnNewOutlookEmail [ConnectorTrigger] function.
DirectConnector/Program.cs Adds conditional OpenTelemetry + Azure Monitor exporter registration.
DirectConnector/ServiceBusFunctions.cs Adds OnQueueMessages [ConnectorTrigger] function.
DirectConnector/SharePointFunctions.cs Replaces the HTTP trigger callback with OnNewSharePointItem [ConnectorTrigger] and logs item counts/properties.
DirectConnector/TeamsFunctions.cs Replaces the HTTP trigger callback with OnNewChannelMessage [ConnectorTrigger] and logs message count.
DirectConnector/WdatpFunctions.cs Adds OnNewRemediationActivity [ConnectorTrigger] function.
DirectConnector/YammerFunctions.cs Adds OnNewYammerMessage [ConnectorTrigger] function (raw string payload).
DirectConnector/host.json Switches telemetry mode to OpenTelemetry and removes Application Insights sampling config.
DirectConnector/DirectConnector.csproj Updates TFM to net10.0 and adds connector trigger + OpenTelemetry-related packages.
DirectConnector.Tests/DirectConnector.Tests.csproj Updates test TFM to net10.0.
DirectConnector.Tests/Office365FunctionsTests.cs Adds tests verifying Office365 trigger logging behavior via Moq.
DirectConnector.Tests/SharePointFunctionsTests.cs Rewrites trigger tests to validate SharePoint trigger logging via Moq.
DirectConnector.Tests/TeamsFunctionsTests.cs Rewrites trigger tests to validate Teams trigger logging via Moq.
.github/workflows/ci.yml Updates CI to use .NET 10.0.x.

[Function("OnNewEmail")]
public void OnNewEmail(
[ConnectorTrigger]
Office365OnNewEmailTriggerPayload payload)
{
contentLength = parsedLength;
}
this._logger.LogInformation("OnNewEmail: Received new email notification.");
[Function("OnNewChannelMessage")]
public void OnNewChannelMessage(
[ConnectorTrigger]
TeamsOnNewChannelMessageTriggerPayload payload)
[Function("OnNewSharePointItem")]
public void OnNewSharePointItem(
[ConnectorTrigger]
SharePointOnlineOnNewItemsTriggerPayload payload)
[Function("OnNewOneDriveFiles")]
public void OnNewOneDriveFiles(
[ConnectorTrigger]
OneDriveForBusinessOnNewFilesTriggerPayload payload)
[Function("OnBlobUpdated")]
public void OnBlobUpdated(
[ConnectorTrigger]
AzureBlobOnUpdatedFilesTriggerPayload payload)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should demonstrate minimum use of the payload such as including metadata in the logged message, e.g. payload size.

[Function("OnEventGridResourceEvent")]
public void OnEventGridResourceEvent(
[ConnectorTrigger]
string payload)
[Function("OnQueueMessagesAvailable")]
public void OnQueueMessagesAvailable(
[ConnectorTrigger]
string payload)
[Function("OnNewYammerMessage")]
public void OnNewYammerMessage(
[ConnectorTrigger]
string payload)
Comment on lines 3 to 7
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "triggerCallback")] HttpRequestData request,
CancellationToken cancellationToken)
[Function("OnNewEmail")]
public void OnNewEmail(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be two distinct samples here - one demonstrating the Functions extension already deserialized strong type as you've added

    [Function("OnNewEmail")]
    public void OnNewEmail(
        [ConnectorTrigger]
        Office365OnNewEmailTriggerPayload payload)

There other preserving the non-Function, any compute demonstration of method attribute based annotation to inform the LSP what payload parsing code needs to be inserted by IntelliSense?

    [ConnectorTriggerMetadata(
       ConnectorName = ConnectorNames.Office365Outlook,
        OperationName = Office365TriggerOperations.OnNewEmail,
        Connection = "Connectors:Office365")]
...

            // NOTE: Use SDK's per-trigger convenience type for typed deserialization.
            // Office365OnNewEmailTriggerPayload is a subclass of TriggerCallbackPayload<GraphClientReceiveMessage>
            // that provides discoverability — the developer no longer needs to know the inner type.
            // The SDK's TriggerCallbackBodyConverter<T> (fix for issue #149) normalizes both
            // single-item and batch shapes so payload.Body.Value is always populated.
            var payload = JsonSerializer.Deserialize<Office365OnNewEmailTriggerPayload>(
                body,
                Office365Functions.JsonOptions);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants