diff --git a/DirectConnector/ArmFunctions.cs b/DirectConnector/ArmFunctions.cs
new file mode 100644
index 0000000..4c5d9e2
--- /dev/null
+++ b/DirectConnector/ArmFunctions.cs
@@ -0,0 +1,262 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+using System.Net;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.Arm;
+using Azure.Connectors.Sdk.Arm.Models;
+using Microsoft.Azure.Functions.Worker;
+using Microsoft.Azure.Functions.Worker.Http;
+using Microsoft.Extensions.Logging;
+
+namespace DirectConnector;
+
+///
+/// Azure Functions demonstrating Azure Resource Manager operations using the generated
+/// from the Azure Connectors SDK.
+///
+///
+/// ARM connector uses OAuth (user-delegated Azure AD token).
+/// The connection requires OAuth consent via the consent link flow.
+///
+public class ArmFunctions
+{
+ private readonly ILogger _logger;
+ private readonly ArmClient _armClient;
+
+ public ArmFunctions(
+ ILogger logger,
+ ArmClient armClient)
+ {
+ this._logger = logger;
+ this._armClient = armClient;
+ }
+
+ ///
+ /// Lists all subscriptions accessible to the authenticated user.
+ ///
+ [Function("ArmListSubscriptions")]
+ public async Task ListSubscriptionsAsync(
+ [HttpTrigger(AuthorizationLevel.Function, "get", Route = "arm/subscriptions")] HttpRequestData request,
+ CancellationToken cancellationToken)
+ {
+ this._logger.LogInformation("ListSubscriptions: Using generated ArmClient.");
+
+ try
+ {
+ var subscriptions = new List();
+ await foreach (var subscription in this._armClient
+ .SubscriptionsListAsync()
+ .WithCancellation(cancellationToken)
+ .ConfigureAwait(continueOnCapturedContext: false))
+ {
+ subscriptions.Add(subscription);
+ }
+
+ this._logger.LogInformation("Found '{Count}' subscriptions.", subscriptions.Count);
+
+ var response = request.CreateResponse(HttpStatusCode.OK);
+ await response
+ .WriteAsJsonAsync(new { success = true, count = subscriptions.Count, subscriptions })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return response;
+ }
+ catch (ConnectorException ex)
+ {
+ this._logger.LogError(ex, "ARM connector error: '{StatusCode}'.", ex.Status);
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ this._logger.LogError(ex, "Error in ListSubscriptions.");
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.InternalServerError);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ }
+
+ ///
+ /// Lists resource groups in a subscription.
+ ///
+ [Function("ArmListResourceGroups")]
+ public async Task ListResourceGroupsAsync(
+ [HttpTrigger(AuthorizationLevel.Function, "get", Route = "arm/subscriptions/{subscriptionId}/resourcegroups")] HttpRequestData request,
+ string subscriptionId,
+ CancellationToken cancellationToken)
+ {
+ this._logger.LogInformation("ListResourceGroups: subscription='{SubscriptionId}'.", subscriptionId);
+
+ try
+ {
+ var resourceGroups = new List();
+ await foreach (var resourceGroup in this._armClient
+ .ResourceGroupsListAsync(subscription: subscriptionId)
+ .WithCancellation(cancellationToken)
+ .ConfigureAwait(continueOnCapturedContext: false))
+ {
+ resourceGroups.Add(resourceGroup);
+ }
+
+ this._logger.LogInformation("Found '{Count}' resource groups.", resourceGroups.Count);
+
+ var response = request.CreateResponse(HttpStatusCode.OK);
+ await response
+ .WriteAsJsonAsync(new { success = true, count = resourceGroups.Count, resourceGroups })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return response;
+ }
+ catch (ConnectorException ex)
+ {
+ this._logger.LogError(ex, "ARM connector error: '{StatusCode}'.", ex.Status);
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ this._logger.LogError(ex, "Error in ListResourceGroups.");
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.InternalServerError);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ }
+
+ ///
+ /// Reads a specific resource by its resource group, provider, and short resource ID.
+ ///
+ [Function("ArmReadResource")]
+ public async Task ReadResourceAsync(
+ [HttpTrigger(AuthorizationLevel.Function, "get", Route = "arm/resource")] HttpRequestData request,
+ CancellationToken cancellationToken)
+ {
+ var subscriptionId = request.Query["subscriptionId"];
+ var resourceGroup = request.Query["resourceGroup"];
+ var provider = request.Query["provider"];
+ var shortResourceId = request.Query["shortResourceId"];
+ var apiVersion = request.Query["apiVersion"];
+
+ if (string.IsNullOrWhiteSpace(subscriptionId) ||
+ string.IsNullOrWhiteSpace(resourceGroup) ||
+ string.IsNullOrWhiteSpace(provider) ||
+ string.IsNullOrWhiteSpace(shortResourceId) ||
+ string.IsNullOrWhiteSpace(apiVersion))
+ {
+ var badRequest = request.CreateResponse(HttpStatusCode.BadRequest);
+ await badRequest
+ .WriteAsJsonAsync(new { error = "Query parameters 'subscriptionId', 'resourceGroup', 'provider', 'shortResourceId', and 'apiVersion' are required." })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return badRequest;
+ }
+
+ this._logger.LogInformation("ReadResource: '{Provider}/{ShortResourceId}' in '{ResourceGroup}'.", provider, shortResourceId, resourceGroup);
+
+ try
+ {
+ var resource = await this._armClient
+ .ResourcesGetByIdAsync(
+ subscription: subscriptionId,
+ resourceGroup: resourceGroup,
+ resourceProvider: provider,
+ shortResourceId: shortResourceId,
+ clientApiVersion: apiVersion,
+ cancellationToken: cancellationToken)
+ .ConfigureAwait(continueOnCapturedContext: false);
+
+ this._logger.LogInformation("Read resource '{Name}' of type '{Type}'.", resource.Name, resource.Type);
+
+ var response = request.CreateResponse(HttpStatusCode.OK);
+ await response
+ .WriteAsJsonAsync(new { success = true, resource })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return response;
+ }
+ catch (ConnectorException ex)
+ {
+ this._logger.LogError(ex, "ARM connector error: '{StatusCode}'.", ex.Status);
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ this._logger.LogError(ex, "Error in ReadResource.");
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.InternalServerError);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ }
+
+ ///
+ /// Lists resources in a resource group.
+ ///
+ [Function("ArmListResources")]
+ public async Task ListResourcesByResourceGroupAsync(
+ [HttpTrigger(AuthorizationLevel.Function, "get", Route = "arm/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/resources")] HttpRequestData request,
+ string subscriptionId,
+ string resourceGroupName,
+ CancellationToken cancellationToken)
+ {
+ this._logger.LogInformation("ListResourcesByResourceGroup: subscription='{SubscriptionId}', resourceGroup='{ResourceGroup}'.", subscriptionId, resourceGroupName);
+
+ try
+ {
+ var resources = new List();
+ await foreach (var resource in this._armClient
+ .ResourceGroupsListResourcesAsync(subscription: subscriptionId, resourceGroup: resourceGroupName)
+ .WithCancellation(cancellationToken)
+ .ConfigureAwait(continueOnCapturedContext: false))
+ {
+ resources.Add(resource);
+ }
+
+ this._logger.LogInformation("Found '{Count}' resources.", resources.Count);
+
+ var response = request.CreateResponse(HttpStatusCode.OK);
+ await response
+ .WriteAsJsonAsync(new { success = true, count = resources.Count, resources })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return response;
+ }
+ catch (ConnectorException ex)
+ {
+ this._logger.LogError(ex, "ARM connector error: '{StatusCode}'.", ex.Status);
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ this._logger.LogError(ex, "Error in ListResourcesByResourceGroup.");
+
+ var errorResponse = request.CreateResponse(HttpStatusCode.InternalServerError);
+ await errorResponse
+ .WriteAsJsonAsync(new { success = false, error = ex.Message })
+ .ConfigureAwait(continueOnCapturedContext: false);
+ return errorResponse;
+ }
+ }
+}
diff --git a/DirectConnector/AzureBlobFunctions.cs b/DirectConnector/AzureBlobFunctions.cs
index 4dc8c38..79d8962 100644
--- a/DirectConnector/AzureBlobFunctions.cs
+++ b/DirectConnector/AzureBlobFunctions.cs
@@ -3,8 +3,9 @@
//------------------------------------------------------------
using System.Net;
-using Microsoft.Azure.Connectors.DirectClient.Azureblob;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.AzureBlob;
+using Azure.Connectors.Sdk.AzureBlob.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
@@ -13,7 +14,7 @@ namespace DirectConnector;
///
/// Azure Functions demonstrating Azure Blob Storage operations using the generated
-/// from the DirectClient SDK.
+/// from the Azure Connectors SDK.
///
///
/// Azure Blob Storage uses key-based auth (accountName + accessKey), not OAuth.
@@ -22,18 +23,18 @@ namespace DirectConnector;
public class AzureBlobFunctions
{
private readonly ILogger _logger;
- private readonly AzureblobClient _azureBlobClient;
+ private readonly AzureBlobClient _azureBlobClient;
public AzureBlobFunctions(
ILogger logger,
- AzureblobClient azureBlobClient)
+ AzureBlobClient azureBlobClient)
{
this._logger = logger;
this._azureBlobClient = azureBlobClient;
}
///
- /// Gets blob metadata using the generated .
+ /// Gets blob metadata using the generated .
/// Exercises the response type.
///
[Function("GetBlobMetadata")]
@@ -41,7 +42,7 @@ public async Task GetBlobMetadataAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "blob/metadata")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("GetBlobMetadata: Using generated AzureblobClient.");
+ this._logger.LogInformation("GetBlobMetadata: Using generated AzureBlobClient.");
var storageAccount = request.Query["account"];
var blobPath = request.Query["path"];
@@ -71,13 +72,13 @@ await response
.ConfigureAwait(continueOnCapturedContext: false);
return response;
}
- catch (AzureblobConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody })
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
}
@@ -94,7 +95,7 @@ await errorResponse
}
///
- /// Downloads blob content using the generated .
+ /// Downloads blob content using the generated .
/// Exercises the byte[] return path.
///
[Function("DownloadBlob")]
@@ -102,7 +103,7 @@ public async Task DownloadBlobAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "blob/download")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("DownloadBlob: Using generated AzureblobClient byte[] response path.");
+ this._logger.LogInformation("DownloadBlob: Using generated AzureBlobClient byte[] response path.");
var storageAccount = request.Query["account"];
var blobPath = request.Query["path"];
@@ -140,13 +141,13 @@ await response.Body
return response;
}
- catch (AzureblobConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody })
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
}
@@ -163,7 +164,7 @@ await errorResponse
}
///
- /// Uploads a blob using the generated .
+ /// Uploads a blob using the generated .
/// Exercises the byte[] input path with response.
///
[Function("UploadBlob")]
@@ -171,7 +172,7 @@ public async Task UploadBlobAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "blob/upload")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("UploadBlob: Using generated AzureblobClient.");
+ this._logger.LogInformation("UploadBlob: Using generated AzureBlobClient.");
var storageAccount = request.Query["account"];
var folder = request.Query["folder"];
@@ -210,13 +211,13 @@ await response
.ConfigureAwait(continueOnCapturedContext: false);
return response;
}
- catch (AzureblobConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody })
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
}
@@ -233,7 +234,7 @@ await errorResponse
}
///
- /// Deletes a blob using the generated .
+ /// Deletes a blob using the generated .
/// Exercises the void (no response body) path.
///
[Function("DeleteBlob")]
@@ -241,7 +242,7 @@ public async Task DeleteBlobAsync(
[HttpTrigger(AuthorizationLevel.Function, "delete", Route = "blob/delete")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("DeleteBlob: Using generated AzureblobClient.");
+ this._logger.LogInformation("DeleteBlob: Using generated AzureBlobClient.");
var storageAccount = request.Query["account"];
var blobId = request.Query["id"];
@@ -271,13 +272,13 @@ await response
.ConfigureAwait(continueOnCapturedContext: false);
return response;
}
- catch (AzureblobConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Azure Blob connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody })
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody })
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
}
diff --git a/DirectConnector/AzureLogAnalyticsFunctions.cs b/DirectConnector/AzureLogAnalyticsFunctions.cs
index 04f3492..1e0ed20 100644
--- a/DirectConnector/AzureLogAnalyticsFunctions.cs
+++ b/DirectConnector/AzureLogAnalyticsFunctions.cs
@@ -3,8 +3,9 @@
//------------------------------------------------------------
using System.Net;
-using Microsoft.Azure.Connectors.DirectClient.Azureloganalytics;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.Azuremonitorlogs;
+using Azure.Connectors.Sdk.Azuremonitorlogs.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
@@ -12,17 +13,23 @@
namespace DirectConnector;
///
-/// Azure Functions demonstrating Azure Log Analytics operations using the generated
-/// from the DirectClient SDK.
+/// Azure Functions demonstrating Azure Monitor Logs operations using the generated
+/// from the Azure Connectors SDK.
///
+///
+/// This connector replaces the deprecated Azure Log Analytics connector.
+/// The file retains the "LogAnalytics" name in routes for backward compatibility.
+///
public class AzureLogAnalyticsFunctions
{
+ private const string OperationalInsightsWorkspaceResourceType = "Microsoft.OperationalInsights/workspaces";
+
private readonly ILogger _logger;
- private readonly AzureloganalyticsClient _logAnalyticsClient;
+ private readonly AzuremonitorlogsClient _logAnalyticsClient;
public AzureLogAnalyticsFunctions(
ILogger logger,
- AzureloganalyticsClient logAnalyticsClient)
+ AzuremonitorlogsClient logAnalyticsClient)
{
this._logger = logger;
this._logAnalyticsClient = logAnalyticsClient;
@@ -37,7 +44,7 @@ public async Task ListSubscriptionsAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "loganalytics/subscriptions")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListLogAnalyticsSubscriptions: Using generated AzureloganalyticsClient from SDK.");
+ this._logger.LogInformation("ListLogAnalyticsSubscriptions: Using generated AzuremonitorlogsClient from SDK.");
try
{
@@ -57,13 +64,13 @@ await response
return response;
}
- catch (AzureloganalyticsConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "ListLogAnalyticsSubscriptions failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "ListLogAnalyticsSubscriptions failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -94,7 +101,7 @@ public async Task ListWorkspacesAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "loganalytics/workspaces")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListLogAnalyticsWorkspaces: Using generated AzureloganalyticsClient from SDK.");
+ this._logger.LogInformation("ListLogAnalyticsWorkspaces: Using generated AzuremonitorlogsClient from SDK.");
var subscription = request.Query["subscription"];
var resourceGroup = request.Query["resourceGroup"];
@@ -111,30 +118,30 @@ await badRequest
try
{
- // Note: SDK returns ResourceGroup type for workspace entries per the connector API schema
- var workspaces = new List();
- await foreach (var workspace in this._logAnalyticsClient
- .ListWorkspaceNamesAsync(subscription: subscription, resourceGroup: resourceGroup)
+ // Note: SDK returns ResourceItem for resource entries per the connector API schema
+ var resources = new List();
+ await foreach (var resource in this._logAnalyticsClient
+ .ListResourcesAsync(subscription: subscription, resourceGroup: resourceGroup, resourceType: AzureLogAnalyticsFunctions.OperationalInsightsWorkspaceResourceType)
.WithCancellation(cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false))
{
- workspaces.Add(workspace);
+ resources.Add(resource);
}
var response = request.CreateResponse(HttpStatusCode.OK);
await response
- .WriteAsJsonAsync(new { success = true, count = workspaces.Count, workspaces }, cancellationToken)
+ .WriteAsJsonAsync(new { success = true, count = resources.Count, workspaces = resources }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return response;
}
- catch (AzureloganalyticsConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "ListLogAnalyticsWorkspaces failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "ListLogAnalyticsWorkspaces failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
diff --git a/DirectConnector/ConnectorFunctions.cs b/DirectConnector/ConnectorFunctions.cs
index 81b52a1..f3dbf0c 100644
--- a/DirectConnector/ConnectorFunctions.cs
+++ b/DirectConnector/ConnectorFunctions.cs
@@ -5,20 +5,23 @@
using System.Net;
using System.Text;
using System.Text.Json;
-using Microsoft.Azure.Connectors.DirectClient.Office365;
-using Microsoft.Azure.Connectors.DirectClient.Sharepointonline;
-using Microsoft.Azure.Connectors.DirectClient.Teams;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.Office365;
+using Azure.Connectors.Sdk.Office365.Models;
+using Azure.Connectors.Sdk.SharePointOnline;
+using Azure.Connectors.Sdk.SharePointOnline.Models;
+using Azure.Connectors.Sdk.Teams;
+using Azure.Connectors.Sdk.Teams.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
-using SharePointBlobMetadata = Microsoft.Azure.Connectors.DirectClient.Sharepointonline.BlobMetadata;
+using SharePointBlobMetadata = Azure.Connectors.Sdk.SharePointOnline.Models.BlobMetadata;
namespace DirectConnector;
///
-/// Azure Functions that use the generated , ,
-/// and from the DirectClient SDK.
+/// Azure Functions that use the generated , ,
+/// and from the Azure Connectors SDK.
///
///
/// Demonstrates DI-based lifetime management, JSON deserialization for structured responses,
@@ -56,7 +59,7 @@ public class ConnectorFunctions
private readonly ILogger _logger;
private readonly Office365Client _office365Client;
- private readonly SharepointonlineClient _sharePointClient;
+ private readonly SharePointOnlineClient _sharePointClient;
private readonly TeamsClient _teamsClient;
///
@@ -69,7 +72,7 @@ public class ConnectorFunctions
public ConnectorFunctions(
ILogger logger,
Office365Client office365Client,
- SharepointonlineClient sharePointClient,
+ SharePointOnlineClient sharePointClient,
TeamsClient teamsClient)
{
this._logger = logger;
@@ -148,9 +151,9 @@ await response
return response;
}
- catch (Office365ConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -158,7 +161,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -212,9 +215,9 @@ await response
return response;
}
- catch (Office365ConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -222,7 +225,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode
+ statusCode = ex.Status
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -246,7 +249,7 @@ await errorResponse
}
///
- /// Gets all SharePoint lists and libraries for a site using the generated .
+ /// Gets all SharePoint lists and libraries for a site using the generated .
///
/// The HTTP request containing the site address.
/// The cancellation token.
@@ -255,7 +258,7 @@ public async Task GetSharePointListsAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "sharepoint/lists")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("GetSharePointLists: Using generated SharepointonlineClient from SDK.");
+ this._logger.LogInformation("GetSharePointLists: Using generated SharePointOnlineClient from SDK.");
var siteAddress = request.Query["site"];
if (string.IsNullOrEmpty(siteAddress))
@@ -290,9 +293,9 @@ await response
return response;
}
- catch (SharepointonlineConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -300,7 +303,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -325,7 +328,7 @@ await errorResponse
}
///
- /// Lists files in a SharePoint folder using the generated .
+ /// Lists files in a SharePoint folder using the generated .
///
///
/// Exercises the model for folder browsing.
@@ -337,7 +340,7 @@ public async Task ListFolderAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "sharepoint/files")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListFolder: Using generated SharepointonlineClient from SDK.");
+ this._logger.LogInformation("ListFolder: Using generated SharePointOnlineClient from SDK.");
var siteAddress = request.Query["site"];
if (string.IsNullOrEmpty(siteAddress))
@@ -386,9 +389,9 @@ await response
return response;
}
- catch (SharepointonlineConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -396,7 +399,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -420,7 +423,7 @@ await errorResponse
/// Downloads file content from SharePoint as binary bytes.
///
///
- /// Exercises the byte[] response path in .
+ /// Exercises the byte[] response path in .
/// The generated CallConnectorAsync detects byte[] as the response type and uses
/// ReadAsByteArrayAsync instead of JSON deserialization.
///
@@ -431,7 +434,7 @@ public async Task DownloadFileAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "sharepoint/download")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("DownloadFile: Using generated SharepointonlineClient byte[] response path.");
+ this._logger.LogInformation("DownloadFile: Using generated SharePointOnlineClient byte[] response path.");
var siteAddress = request.Query["site"];
var filePath = request.Query["path"];
@@ -471,9 +474,9 @@ await response.Body
return response;
}
- catch (SharepointonlineConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -481,7 +484,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -505,7 +508,7 @@ await errorResponse
/// Uploads a file to a SharePoint document library.
///
///
- /// Exercises the byte[] input path in .
+ /// Exercises the byte[] input path in .
/// Accepts a JSON body with base64-encoded content or plain text, and uploads it to
/// the specified SharePoint folder.
///
@@ -516,7 +519,7 @@ public async Task UploadFileAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "sharepoint/upload")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("UploadFile: Using generated SharepointonlineClient byte[] input path.");
+ this._logger.LogInformation("UploadFile: Using generated SharePointOnlineClient byte[] input path.");
try
{
@@ -593,9 +596,9 @@ await response
return response;
}
- catch (SharepointonlineConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "SharePoint connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -603,7 +606,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -670,9 +673,9 @@ await response.Body
return response;
}
- catch (Office365ConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -680,7 +683,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode
+ statusCode = ex.Status
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -928,9 +931,9 @@ await response
return response;
}
- catch (TeamsConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -938,7 +941,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -1005,9 +1008,9 @@ await response
return response;
}
- catch (TeamsConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -1015,7 +1018,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -1098,9 +1101,9 @@ await response
return response;
}
- catch (TeamsConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -1108,7 +1111,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -1178,7 +1181,7 @@ await badRequest
// The actual message body properties are determined at runtime by the connector's schema
// discovery endpoint. With [JsonExtensionData] on AdditionalProperties, arbitrary properties
// are now serialized correctly. Populate the dictionary with the expected message fields.
- var messageRequest = new Microsoft.Azure.Connectors.DirectClient.Teams.DynamicPostMessageRequest();
+ var messageRequest = new Azure.Connectors.Sdk.Teams.Models.DynamicPostMessageRequest();
messageRequest.AdditionalProperties["recipient"] = JsonSerializer.SerializeToElement(
new
{
@@ -1210,9 +1213,9 @@ await response
return response;
}
- catch (TeamsConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Teams connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -1220,7 +1223,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -1323,9 +1326,9 @@ await response
return response;
}
- catch (Office365ConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "Connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -1333,7 +1336,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
diff --git a/DirectConnector/ConnectorTriggerMetadataAttribute.cs b/DirectConnector/ConnectorTriggerMetadataAttribute.cs
index fd4ac8e..988ba0c 100644
--- a/DirectConnector/ConnectorTriggerMetadataAttribute.cs
+++ b/DirectConnector/ConnectorTriggerMetadataAttribute.cs
@@ -28,13 +28,13 @@ namespace DirectConnector;
public sealed class ConnectorTriggerMetadataAttribute : Attribute
{
///
- /// The connector API name. Use constants from .
+ /// The connector API name. Use constants from .
///
public string ConnectorName { get; set; } = "";
///
/// The trigger operation name. Use constants from the connector's *TriggerOperations class
- /// (e.g., ).
+ /// (e.g., ).
///
public string OperationName { get; set; } = "";
diff --git a/DirectConnector/DirectConnector.csproj b/DirectConnector/DirectConnector.csproj
index 25131d0..5f49bed 100644
--- a/DirectConnector/DirectConnector.csproj
+++ b/DirectConnector/DirectConnector.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/DirectConnector/ExceptionExtensions.cs b/DirectConnector/ExceptionExtensions.cs
new file mode 100644
index 0000000..736cf1a
--- /dev/null
+++ b/DirectConnector/ExceptionExtensions.cs
@@ -0,0 +1,28 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+using System.Runtime.InteropServices;
+
+namespace DirectConnector;
+
+///
+/// Extension methods for exception handling.
+/// Provides the guard that was available in earlier SDK versions
+/// but made internal in Azure.Connectors.Sdk 0.9.0.
+///
+internal static class ExceptionExtensions
+{
+ ///
+ /// Determines whether the exception is fatal and should not be caught.
+ ///
+ /// The exception to check.
+ public static bool IsFatal(this Exception exception)
+ {
+ return exception is OutOfMemoryException or
+ StackOverflowException or
+ AccessViolationException or
+ SEHException or
+ ThreadAbortException;
+ }
+}
diff --git a/DirectConnector/MqFunctions.cs b/DirectConnector/MqFunctions.cs
index f5a1918..09f93db 100644
--- a/DirectConnector/MqFunctions.cs
+++ b/DirectConnector/MqFunctions.cs
@@ -4,8 +4,9 @@
using System.Net;
using System.Text.Json;
-using Microsoft.Azure.Connectors.DirectClient.Mq;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.Mq;
+using Azure.Connectors.Sdk.Mq.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
@@ -14,7 +15,7 @@ namespace DirectConnector;
///
/// Azure Functions demonstrating IBM MQ operations using the generated
-/// from the DirectClient SDK.
+/// from the Azure Connectors SDK.
///
///
/// IBM MQ uses parameter-based auth (server, queue manager, channel, credentials).
@@ -85,13 +86,13 @@ await response
return response;
}
- catch (MqConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MQ send failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MQ send failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -156,13 +157,13 @@ await response
return response;
}
- catch (MqConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MQ browse failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MQ browse failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -231,13 +232,13 @@ await response
return response;
}
- catch (MqConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MQ browse batch failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MQ browse batch failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -302,13 +303,13 @@ await response
return response;
}
- catch (MqConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MQ receive failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MQ receive failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -378,13 +379,13 @@ await response
return response;
}
- catch (MqConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MQ delete failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MQ delete failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
diff --git a/DirectConnector/MsGraphFunctions.cs b/DirectConnector/MsGraphFunctions.cs
index 7be6cbb..837e1a7 100644
--- a/DirectConnector/MsGraphFunctions.cs
+++ b/DirectConnector/MsGraphFunctions.cs
@@ -3,8 +3,9 @@
//------------------------------------------------------------
using System.Net;
-using Microsoft.Azure.Connectors.DirectClient.Msgraphgroupsanduser;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.MsGraphGroupsAndUsers;
+using Azure.Connectors.Sdk.MsGraphGroupsAndUsers.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
@@ -13,7 +14,7 @@ namespace DirectConnector;
///
/// Azure Functions demonstrating MS Graph Groups & Users operations using the generated
-/// from the DirectClient SDK.
+/// from the Azure Connectors SDK.
///
///
/// Exercises user listing, group search, and group property retrieval.
@@ -21,7 +22,7 @@ namespace DirectConnector;
public class MsGraphFunctions
{
private readonly ILogger _logger;
- private readonly MsgraphgroupsanduserClient _msGraphClient;
+ private readonly MsGraphGroupsAndUsersClient _msGraphClient;
///
/// Initializes a new instance of the class.
@@ -30,14 +31,14 @@ public class MsGraphFunctions
/// The DI-injected MS Graph Groups & Users client (disposed by the host).
public MsGraphFunctions(
ILogger logger,
- MsgraphgroupsanduserClient msGraphClient)
+ MsGraphGroupsAndUsersClient msGraphClient)
{
this._logger = logger;
this._msGraphClient = msGraphClient;
}
///
- /// Lists a page of users in the tenant using the generated .
+ /// Lists a page of users in the tenant using the generated .
///
/// The HTTP request.
/// The cancellation token.
@@ -46,7 +47,7 @@ public async Task ListGraphUsersAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "graph/users")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListGraphUsers: Using generated MsgraphgroupsanduserClient from SDK.");
+ this._logger.LogInformation("ListGraphUsers: Using generated MsGraphGroupsAndUsersClient from SDK.");
try
{
@@ -66,9 +67,9 @@ await response
return response;
}
- catch (MsgraphgroupsanduserConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MS Graph connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MS Graph connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -76,7 +77,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -97,7 +98,7 @@ await errorResponse
}
///
- /// Searches for groups by display name using the generated .
+ /// Searches for groups by display name using the generated .
///
/// The HTTP request with optional 'search' query parameter.
/// The cancellation token.
@@ -106,7 +107,7 @@ public async Task ListGraphGroupsAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "graph/groups")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListGraphGroups: Using generated MsgraphgroupsanduserClient from SDK.");
+ this._logger.LogInformation("ListGraphGroups: Using generated MsGraphGroupsAndUsersClient from SDK.");
var rawSearch = request.Query["search"];
var search = string.IsNullOrWhiteSpace(rawSearch) ? null : rawSearch;
@@ -130,9 +131,9 @@ await response
return response;
}
- catch (MsgraphgroupsanduserConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MS Graph connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MS Graph connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -140,7 +141,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -161,7 +162,7 @@ await errorResponse
}
///
- /// Gets properties of a specific group using the generated .
+ /// Gets properties of a specific group using the generated .
///
/// The HTTP request with 'groupId' query parameter.
/// The cancellation token.
@@ -170,7 +171,7 @@ public async Task GetGraphGroupPropertiesAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "graph/groups/properties")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("GetGraphGroupProperties: Using generated MsgraphgroupsanduserClient from SDK.");
+ this._logger.LogInformation("GetGraphGroupProperties: Using generated MsGraphGroupsAndUsersClient from SDK.");
var rawGroupId = request.Query["groupId"];
var groupId = rawGroupId?.Trim();
@@ -206,9 +207,9 @@ await response
return response;
}
- catch (MsgraphgroupsanduserConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "MS Graph connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "MS Graph connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -216,7 +217,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
diff --git a/DirectConnector/Office365UsersFunctions.cs b/DirectConnector/Office365UsersFunctions.cs
index d6d4d41..5dc6a86 100644
--- a/DirectConnector/Office365UsersFunctions.cs
+++ b/DirectConnector/Office365UsersFunctions.cs
@@ -3,8 +3,9 @@
//------------------------------------------------------------
using System.Net;
-using Microsoft.Azure.Connectors.DirectClient.Office365users;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.Office365users;
+using Azure.Connectors.Sdk.Office365users.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
@@ -13,7 +14,7 @@ namespace DirectConnector;
///
/// Azure Functions demonstrating Office 365 Users operations using the generated
-/// from the DirectClient SDK.
+/// from the Azure Connectors SDK.
///
public class Office365UsersFunctions
{
@@ -48,13 +49,13 @@ await response
return response;
}
- catch (Office365usersConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "GetMyProfile failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "GetMyProfile failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -97,13 +98,13 @@ await response
return response;
}
- catch (Office365usersConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "GetUserProfile failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "GetUserProfile failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -146,13 +147,13 @@ await response
return response;
}
- catch (Office365usersConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "GetManager failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "GetManager failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -195,13 +196,13 @@ await response
return response;
}
- catch (Office365usersConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "GetDirectReports failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "GetDirectReports failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
@@ -260,13 +261,13 @@ await response
return response;
}
- catch (Office365usersConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "SearchUsers failed with status '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "SearchUsers failed with status '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
- .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.StatusCode, details = ex.ResponseBody }, cancellationToken)
+ .WriteAsJsonAsync(new { success = false, error = ex.Message, statusCode = ex.Status, details = ex.ResponseBody }, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
return errorResponse;
diff --git a/DirectConnector/OneDriveFunctions.cs b/DirectConnector/OneDriveFunctions.cs
index f46dbdc..3460486 100644
--- a/DirectConnector/OneDriveFunctions.cs
+++ b/DirectConnector/OneDriveFunctions.cs
@@ -5,18 +5,19 @@
using System.Net;
using System.Text;
using System.Text.Json;
-using Microsoft.Azure.Connectors.DirectClient.Onedriveforbusiness;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.OneDriveForBusiness;
+using Azure.Connectors.Sdk.OneDriveForBusiness.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
-using OneDriveBlobMetadata = Microsoft.Azure.Connectors.DirectClient.Onedriveforbusiness.BlobMetadata;
+using OneDriveBlobMetadata = Azure.Connectors.Sdk.OneDriveForBusiness.Models.BlobMetadata;
namespace DirectConnector;
///
/// Azure Functions demonstrating OneDrive for Business operations using the generated
-/// from the DirectClient SDK.
+/// from the Azure Connectors SDK.
///
///
/// Exercises folder listing, file download/upload, search, sharing links,
@@ -49,7 +50,7 @@ public class OneDriveFunctions
};
private readonly ILogger _logger;
- private readonly OnedriveforbusinessClient _oneDriveClient;
+ private readonly OneDriveForBusinessClient _oneDriveClient;
///
/// Initializes a new instance of the class.
@@ -58,7 +59,7 @@ public class OneDriveFunctions
/// The DI-injected OneDrive for Business client (disposed by the host).
public OneDriveFunctions(
ILogger logger,
- OnedriveforbusinessClient oneDriveClient)
+ OneDriveForBusinessClient oneDriveClient)
{
this._logger = logger;
this._oneDriveClient = oneDriveClient;
@@ -74,7 +75,7 @@ public async Task ListOneDriveRootAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "onedrive/root")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListOneDriveRoot: Using generated OnedriveforbusinessClient from SDK.");
+ this._logger.LogInformation("ListOneDriveRoot: Using generated OneDriveForBusinessClient from SDK.");
try
{
@@ -103,9 +104,9 @@ await response
return response;
}
- catch (OnedriveforbusinessConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -113,7 +114,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -137,7 +138,7 @@ await errorResponse
/// Lists files in a specific OneDrive folder.
///
///
- /// Exercises which returns an
+ /// Exercises which returns an
/// that automatically follows pagination across all pages.
///
/// The HTTP request containing the folder identifier.
@@ -147,7 +148,7 @@ public async Task ListOneDriveFolderAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "onedrive/files")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("ListOneDriveFolder: Using generated OnedriveforbusinessClient from SDK.");
+ this._logger.LogInformation("ListOneDriveFolder: Using generated OneDriveForBusinessClient from SDK.");
var folderId = request.Query["folder"];
if (string.IsNullOrEmpty(folderId))
@@ -194,9 +195,9 @@ await response
return response;
}
- catch (OnedriveforbusinessConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -204,7 +205,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -228,7 +229,7 @@ await errorResponse
/// Downloads a file from OneDrive for Business as binary bytes.
///
///
- /// Exercises the byte[] response path in .
+ /// Exercises the byte[] response path in .
///
/// The HTTP request containing the file path.
/// The cancellation token.
@@ -237,7 +238,7 @@ public async Task DownloadOneDriveFileAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "onedrive/download")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("DownloadOneDriveFile: Using generated OnedriveforbusinessClient byte[] response path.");
+ this._logger.LogInformation("DownloadOneDriveFile: Using generated OneDriveForBusinessClient byte[] response path.");
var filePath = request.Query["path"];
if (string.IsNullOrEmpty(filePath))
@@ -272,9 +273,9 @@ await response.Body
return response;
}
- catch (OnedriveforbusinessConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -282,7 +283,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -306,7 +307,7 @@ await errorResponse
/// Uploads a file to OneDrive for Business.
///
///
- /// Exercises the byte[] input path in .
+ /// Exercises the byte[] input path in .
///
/// The HTTP request containing upload details.
/// The cancellation token.
@@ -315,7 +316,7 @@ public async Task UploadOneDriveFileAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "onedrive/upload")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("UploadOneDriveFile: Using generated OnedriveforbusinessClient byte[] input path.");
+ this._logger.LogInformation("UploadOneDriveFile: Using generated OneDriveForBusinessClient byte[] input path.");
try
{
@@ -391,9 +392,9 @@ await response
return response;
}
- catch (OnedriveforbusinessConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -401,7 +402,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -431,7 +432,7 @@ public async Task SearchOneDriveFilesAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "onedrive/search")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("SearchOneDriveFiles: Using generated OnedriveforbusinessClient from SDK.");
+ this._logger.LogInformation("SearchOneDriveFiles: Using generated OneDriveForBusinessClient from SDK.");
var query = request.Query["query"];
if (string.IsNullOrEmpty(query))
@@ -477,9 +478,9 @@ await response
return response;
}
- catch (OnedriveforbusinessConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -487,7 +488,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -517,7 +518,7 @@ public async Task CreateOneDriveShareLinkAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "onedrive/share")] HttpRequestData request,
CancellationToken cancellationToken)
{
- this._logger.LogInformation("CreateOneDriveShareLink: Using generated OnedriveforbusinessClient from SDK.");
+ this._logger.LogInformation("CreateOneDriveShareLink: Using generated OneDriveForBusinessClient from SDK.");
try
{
@@ -577,9 +578,9 @@ await response
return response;
}
- catch (OnedriveforbusinessConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "OneDrive connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -587,7 +588,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
})
.ConfigureAwait(continueOnCapturedContext: false);
@@ -627,7 +628,7 @@ await errorResponse
/// Object body (OnNewFilesV2 / OnUpdatedFilesV2)
///
/// The body field is a {"value":[...]} object with items.
- /// The payload deserializes to .
+ /// The payload deserializes to .
///
///
///
@@ -636,8 +637,8 @@ await errorResponse
/// The cancellation token.
[Function("OneDriveTriggerCallback")]
[ConnectorTriggerMetadata(
- ConnectorName = ConnectorNames.Onedriveforbusiness,
- OperationName = OnedriveforbusinessTriggerOperations.OnNewFiles,
+ ConnectorName = ConnectorNames.OneDriveForBusiness,
+ OperationName = OneDriveForBusinessTriggerOperations.OnNewFiles,
Connection = "Connectors:OneDrive")]
public async Task OneDriveTriggerCallbackAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "onedriveTriggerCallback")] HttpRequestData request,
@@ -758,7 +759,7 @@ await binaryResponse
// NOTE: OnNewFilesV2 / OnUpdatedFilesV2 (properties-only trigger).
// The "body" field is a {"value":[...]} object with BlobMetadata items.
- var payload = JsonSerializer.Deserialize(
+ var payload = JsonSerializer.Deserialize(
body,
OneDriveFunctions.JsonOptions);
diff --git a/DirectConnector/Program.cs b/DirectConnector/Program.cs
index e88984c..15d9a97 100644
--- a/DirectConnector/Program.cs
+++ b/DirectConnector/Program.cs
@@ -2,22 +2,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
-using DirectConnector.Configuration;
-using Microsoft.Azure.Connectors.DirectClient.Azureblob;
-using Microsoft.Azure.Connectors.DirectClient.Azureloganalytics;
-using Microsoft.Azure.Connectors.DirectClient.Mq;
-using Microsoft.Azure.Connectors.DirectClient.Msgraphgroupsanduser;
-using Microsoft.Azure.Connectors.DirectClient.Office365;
-using Microsoft.Azure.Connectors.DirectClient.Office365users;
-using Microsoft.Azure.Connectors.DirectClient.Onedriveforbusiness;
-using Microsoft.Azure.Connectors.DirectClient.Sharepointonline;
-using Microsoft.Azure.Connectors.DirectClient.Smtp;
-using Microsoft.Azure.Connectors.DirectClient.Teams;
+using Azure.Connectors.Sdk;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Options;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
@@ -25,137 +14,27 @@
{
var configuration = hostContext.Configuration;
- // NOTE: Bind connector options from configuration.
- // This uses the Options pattern for hierarchical, validated configuration.
- // See: https://learn.microsoft.com/dotnet/core/extensions/options
- services.AddOptions()
- .Bind(configuration.GetSection(ConnectorOptions.SectionName))
- .ValidateDataAnnotations()
- .ValidateOnStart();
-
- services.AddHttpClient();
-
- // NOTE: Register generated connector clients as singletons.
- // The factory overload lets DI own the instance lifetime and call Dispose,
- // which exercises the ownership-based disposal pattern: the client will
- // dispose its internally-created HttpClient and DefaultAzureCredential.
- // NOTE: Validation of ConnectionRuntimeUrl is handled by
- // [Required] attribute + ValidateOnStart() at host initialization.
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- // NOTE: When ManagedIdentityClientId is null, use the default constructor so
- // the client relies on DefaultAzureCredential. When ManagedIdentityClientId is non-null
- // (empty string = system-assigned MSI, non-empty = user-assigned MSI), use the MSI constructor.
- return options.Office365.ManagedIdentityClientId != null
- ? new Office365Client(
- options.Office365.ConnectionRuntimeUrl,
- options.Office365.ManagedIdentityClientId)
- : new Office365Client(options.Office365.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- // NOTE: When ManagedIdentityClientId is null, use the default constructor so
- // the client relies on DefaultAzureCredential. When ManagedIdentityClientId is non-null
- // (empty string = system-assigned MSI, non-empty = user-assigned MSI), use the MSI constructor.
- return options.SharePoint.ManagedIdentityClientId != null
- ? new SharepointonlineClient(
- options.SharePoint.ConnectionRuntimeUrl,
- options.SharePoint.ManagedIdentityClientId)
- : new SharepointonlineClient(options.SharePoint.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.Teams.ManagedIdentityClientId != null
- ? new TeamsClient(
- options.Teams.ConnectionRuntimeUrl,
- options.Teams.ManagedIdentityClientId)
- : new TeamsClient(options.Teams.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.OneDrive.ManagedIdentityClientId != null
- ? new OnedriveforbusinessClient(
- options.OneDrive.ConnectionRuntimeUrl,
- options.OneDrive.ManagedIdentityClientId)
- : new OnedriveforbusinessClient(options.OneDrive.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.MsGraph.ManagedIdentityClientId != null
- ? new MsgraphgroupsanduserClient(
- options.MsGraph.ConnectionRuntimeUrl,
- options.MsGraph.ManagedIdentityClientId)
- : new MsgraphgroupsanduserClient(options.MsGraph.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.AzureBlob.ManagedIdentityClientId != null
- ? new AzureblobClient(
- options.AzureBlob.ConnectionRuntimeUrl,
- options.AzureBlob.ManagedIdentityClientId)
- : new AzureblobClient(options.AzureBlob.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.Smtp.ManagedIdentityClientId != null
- ? new SmtpClient(
- options.Smtp.ConnectionRuntimeUrl,
- options.Smtp.ManagedIdentityClientId)
- : new SmtpClient(options.Smtp.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.Mq.ManagedIdentityClientId != null
- ? new MqClient(
- options.Mq.ConnectionRuntimeUrl,
- options.Mq.ManagedIdentityClientId)
- : new MqClient(options.Mq.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.Office365Users.ManagedIdentityClientId != null
- ? new Office365usersClient(
- options.Office365Users.ConnectionRuntimeUrl,
- options.Office365Users.ManagedIdentityClientId)
- : new Office365usersClient(options.Office365Users.ConnectionRuntimeUrl);
- });
-
- services.AddSingleton(serviceProvider =>
- {
- var options = serviceProvider.GetRequiredService>().Value;
-
- return options.AzureLogAnalytics.ManagedIdentityClientId != null
- ? new AzureloganalyticsClient(
- options.AzureLogAnalytics.ConnectionRuntimeUrl,
- options.AzureLogAnalytics.ManagedIdentityClientId)
- : new AzureloganalyticsClient(options.AzureLogAnalytics.ConnectionRuntimeUrl);
- });
+ // NOTE: Register a TokenCredential for connector clients.
+ // In Development, use DefaultAzureCredential (supports CLI, env vars, etc.).
+ // In Production, the SDK defaults to system-assigned managed identity
+ // when no TokenCredential is registered in DI.
+ if (hostContext.HostingEnvironment.IsDevelopment())
+ {
+ services.AddSingleton(
+ new Azure.Identity.DefaultAzureCredential());
+ }
+
+ services.AddOffice365Client(configuration.GetSection("Connectors:Office365"));
+ services.AddSharePointOnlineClient(configuration.GetSection("Connectors:SharePoint"));
+ services.AddTeamsClient(configuration.GetSection("Connectors:Teams"));
+ services.AddOneDriveForBusinessClient(configuration.GetSection("Connectors:OneDrive"));
+ services.AddMsGraphGroupsAndUsersClient(configuration.GetSection("Connectors:MsGraph"));
+ services.AddAzureBlobClient(configuration.GetSection("Connectors:AzureBlob"));
+ services.AddSmtpClient(configuration.GetSection("Connectors:Smtp"));
+ services.AddMqClient(configuration.GetSection("Connectors:Mq"));
+ services.AddOffice365usersClient(configuration.GetSection("Connectors:Office365Users"));
+ services.AddAzuremonitorlogsClient(configuration.GetSection("Connectors:AzureMonitorLogs"));
+ services.AddArmClient(configuration.GetSection("Connectors:Arm"));
})
.Build();
diff --git a/DirectConnector/SmtpFunctions.cs b/DirectConnector/SmtpFunctions.cs
index d84a1ce..3d6a35d 100644
--- a/DirectConnector/SmtpFunctions.cs
+++ b/DirectConnector/SmtpFunctions.cs
@@ -4,8 +4,9 @@
using System.Net;
using System.Text.Json;
-using Microsoft.Azure.Connectors.DirectClient.Smtp;
-using Microsoft.Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk;
+using Azure.Connectors.Sdk.Smtp;
+using Azure.Connectors.Sdk.Smtp.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
@@ -14,7 +15,7 @@ namespace DirectConnector;
///
/// Azure Functions demonstrating SMTP operations using the generated
-/// from the DirectClient SDK.
+/// from the Azure Connectors SDK.
///
public class SmtpFunctions
{
@@ -91,9 +92,9 @@ await response
return response;
}
- catch (SmtpConnectorException ex)
+ catch (ConnectorException ex)
{
- this._logger.LogError(ex, "SMTP connector error: '{StatusCode}'.", ex.StatusCode);
+ this._logger.LogError(ex, "SMTP connector error: '{StatusCode}'.", ex.Status);
var errorResponse = request.CreateResponse(HttpStatusCode.BadGateway);
await errorResponse
@@ -101,7 +102,7 @@ await errorResponse
{
success = false,
error = ex.Message,
- statusCode = ex.StatusCode,
+ statusCode = ex.Status,
details = ex.ResponseBody
}, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
diff --git a/DirectConnector/local.settings.json.template b/DirectConnector/local.settings.json.template
index e068f83..f8cc022 100644
--- a/DirectConnector/local.settings.json.template
+++ b/DirectConnector/local.settings.json.template
@@ -40,8 +40,12 @@
"__comment_Office365Users_MSI": "To use managed identity, remove the __ prefix from the key below. Use empty string for system-assigned MSI, or a client ID GUID for user-assigned MSI.",
"__Connectors:Office365Users:ManagedIdentityClientId": "",
- "Connectors:AzureLogAnalytics:ConnectionRuntimeUrl": "https://YOUR-INSTANCE.azure-apihub.net/apim/azureloganalytics/YOUR-CONNECTION-ID",
- "__comment_AzureLogAnalytics_MSI": "To use managed identity, remove the __ prefix from the key below. Use empty string for system-assigned MSI, or a client ID GUID for user-assigned MSI.",
- "__Connectors:AzureLogAnalytics:ManagedIdentityClientId": ""
+ "Connectors:AzureMonitorLogs:ConnectionRuntimeUrl": "https://YOUR-INSTANCE.azure-apihub.net/apim/azuremonitorlogs/YOUR-CONNECTION-ID",
+ "__comment_AzureMonitorLogs_MSI": "To use managed identity, remove the __ prefix from the key below. Use empty string for system-assigned MSI, or a client ID GUID for user-assigned MSI.",
+ "__Connectors:AzureMonitorLogs:ManagedIdentityClientId": "",
+
+ "Connectors:Arm:ConnectionRuntimeUrl": "https://YOUR-INSTANCE.azure-apihub.net/apim/arm/YOUR-CONNECTION-ID",
+ "__comment_Arm_MSI": "To use managed identity, remove the __ prefix from the key below. Use empty string for system-assigned MSI, or a client ID GUID for user-assigned MSI.",
+ "__Connectors:Arm:ManagedIdentityClientId": ""
}
}
diff --git a/README.md b/README.md
index 1388b16..1e02a39 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ Sample Azure Functions demonstrating the [Azure Connectors .NET SDK](https://git
## What's Inside
-The `DirectConnector/` project is an Azure Functions (isolated worker) app with 40 sample functions across 10 connectors. Newer connectors have dedicated Functions classes; the original three (Office 365, SharePoint, Teams) share `ConnectorFunctions.cs`:
+The `DirectConnector/` project is an Azure Functions (isolated worker) app with sample functions across 11 connectors. Newer connectors have dedicated Functions classes; the original three (Office 365, SharePoint, Teams) share `ConnectorFunctions.cs`:
| File | Connector | Sample Operations |
|------|-----------|-------------------|
@@ -28,7 +28,8 @@ The `DirectConnector/` project is an Azure Functions (isolated worker) app with
| MqFunctions.cs | IBM MQ | Send, browse, receive, delete messages |
| SmtpFunctions.cs | SMTP | Send email via SMTP |
| AzureBlobFunctions.cs | Azure Blob Storage | Upload, download, get metadata, delete blobs |
-| AzureLogAnalyticsFunctions.cs | Azure Log Analytics | List subscriptions, list workspaces |
+| AzureLogAnalyticsFunctions.cs | Azure Monitor Logs | List subscriptions, list resources |
+| ArmFunctions.cs | Azure Resource Manager (ARM) | List subscriptions, resource groups, read resources |
### Key Patterns Demonstrated