Skill Set Matrix
Skill Name Years Experience Last Used
Certified Software Engineering / Development 20 2024
Certified Solutions Architecture (hands-on) 12 2024
Cloud Computing: Certified Azure Expert 13 2024
C#, C++, Java, Javascript, TSQL, YAML 22 2024
Razor; MVC; Blazor 22 2024
RDBMS: MSSQL; Azure SQLl TSQL; PSQL 9 2024
No SQL: Solr; Cosmos; Hadoop 9 2024
Javascript: JQuery; Chart JS; Angular; React 9 2024
.Net Core 9 2024
.Net Framework 12 2024
Micro-Services, Rest API’s 12 2024
Identity: Entra; OKTA; oAuth2; SAML 12 2024
Microsoft Graph API 8 2024
Plugins and Extensions 16 2024
CI/CD Azure DevOps 16 2024
AI, ML, NLP, ChatGPT 16 2024
Code Sample C# Azure Functional App
Functional App to call securely call Microsoft Graph API
  • Multi-Tenant support
  • Azure Functional App in .Net Core V8
  • Async Methods to get Entra Users
  • Async Methods to get Entra Groups
  • Uses Managed Identity to secure Secrets

[Function("Groups")]
public async Task GetGroupsAsync([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
{
EntraGroups? entraGroups = null;

_logger.LogInformation("C# HTTP trigger function processed a request.");

var requestBody = await new StreamReader(req.Body).ReadToEndAsync();

var request = JsonConvert.DeserializeObject(requestBody);

var tenantUId = request?.TenantUId.ToString("D");

var clientId = Environment.GetEnvironmentVariable("ClientId");
var clientSecret = Environment.GetEnvironmentVariable("ClientSecret");

try
{
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};

var clientSecretCredential = new ClientSecretCredential(
request?.TenantUId.ToString("D"), clientId, clientSecret, options);

var graphServiceClient = new GraphServiceClient(clientSecretCredential, scopes);

var groupList = new List();

var groupsResponse = await graphServiceClient
.Groups
.GetAsync(requestConfiguration => {
requestConfiguration.QueryParameters.Filter = $"groupTypes/any(c: c eq 'Unified')";
requestConfiguration.QueryParameters.Select = new string[] { "id", "displayName", "description", "Mail", "Members", "createdDateTime" }; requestConfiguration.QueryParameters.Top = 60;
requestConfiguration.Headers.Add("ConsistencyLevel", "eventual");
});
var grpIterator = PageIterator
.CreatePageIterator(graphServiceClient, groupsResponse, (group) => { groupList.Add(group); return true; });

await grpIterator.IterateAsync();

entraGroups = new EntraGroups();

foreach (var group in groupList)
{
var entraGroup = new EntraGroup
{
Id = new Guid(group.Id),
Name = group.DisplayName,
Description = group.Description,
Email = group.Mail
};

entraGroups.Items.Add(entraGroup);
}
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());

return new ObjectResult(new { statusCode = 500, Message = ex.Message });
}

return new OkObjectResult(entraGroups);
}