├── README.md ├── Computer Vision POC ├── demoIdCard.png ├── groupOfPeople.jpg ├── README.md └── MsOCR_Demo.ipynb ├── Service Bus Queue ├── BasicEventBus │ ├── BasicEventBus.csproj │ ├── Contracts │ │ ├── IEvent.cs │ │ ├── IEventBusService.cs │ │ ├── IEventHandler.cs │ │ └── IEventBusSubscriptionsManager.cs │ └── EventBusSubscriptionsManager.cs ├── ServiceBusQueueAPI │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── Events │ │ ├── SampleDemo1Event.cs │ │ └── SampleDemo2Event.cs │ ├── EventHandlers │ │ ├── SampleDemo1EventHandler.cs │ │ └── SampleDemo2EventHandler.cs │ ├── ServiceBusQueueAPI.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Controllers │ │ └── HomeController.cs │ └── Startup.cs ├── AzureEventServiceBus │ ├── IEventConsumerService.cs │ ├── AzureEventServiceBus.csproj │ ├── HostedBackgroundService.cs │ ├── EventBusService.cs │ └── EventConsumerService.cs └── ServiceBusQueue.sln ├── Service Bus Queue Topics ├── BasicEventBus │ ├── BasicEventBus.csproj │ ├── Contracts │ │ ├── IEvent.cs │ │ ├── IEventBusService.cs │ │ ├── IEventHandler.cs │ │ └── IEventBusSubscriptionsManager.cs │ └── EventBusSubscriptionsManager.cs ├── ServiceBusTopicsAPI │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── EventHandlers │ │ ├── WeekdaySubscriptionHandler.cs │ │ └── WeekendSubscriptionHandler.cs │ ├── ServiceBusTopicsAPI.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Controllers │ │ └── HomeController.cs │ └── Startup.cs ├── AzureEventServiceBus │ ├── IEventConsumerService.cs │ ├── Constants.cs │ ├── Events │ │ └── TodoTaskCreatedEvent.cs │ ├── AzureEventServiceBus.csproj │ ├── HostedBackgroundService.cs │ ├── EventBusService.cs │ └── EventConsumerService.cs └── ServiceBusTopics.sln ├── Azure Key Vault ├── ServiceBusQueueAPI │ ├── appsettings.json │ ├── Events │ │ ├── SampleDemoEvent.cs │ │ └── EventBusService.cs │ ├── ServiceBusQueueAPI.csproj │ ├── Controllers │ │ └── HomeController.cs │ ├── Properties │ │ └── launchSettings.json │ ├── AzureVaultConfiguration │ │ ├── PrefixKeyVaultSecretManager.cs │ │ └── AzureKeyVaultCertificationExtension.cs │ ├── Startup.cs │ └── Program.cs └── ServiceBusQueueWithAzureKeyVault.sln ├── Azure Function ├── HttpTriggerFunctionApp │ ├── Properties │ │ ├── serviceDependencies.json │ │ └── serviceDependencies.local.json │ ├── host.json │ ├── HttpTriggerFunctionApp.csproj │ ├── Function1.cs │ └── .gitignore ├── OueueTriggeredFunctionApp │ ├── Properties │ │ ├── serviceDependencies.json │ │ └── serviceDependencies.local.json │ ├── host.json │ ├── OueueTriggeredFunctionApp.csproj │ ├── Function1.cs │ └── .gitignore └── Azure Function.sln └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # Azure-Tutorial 2 | -------------------------------------------------------------------------------- /Computer Vision POC/demoIdCard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/Azure-Tutorial/HEAD/Computer Vision POC/demoIdCard.png -------------------------------------------------------------------------------- /Computer Vision POC/groupOfPeople.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/Azure-Tutorial/HEAD/Computer Vision POC/groupOfPeople.jpg -------------------------------------------------------------------------------- /Service Bus Queue/BasicEventBus/BasicEventBus.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/BasicEventBus/BasicEventBus.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Configuration": { 3 | "ConnectionString": "", 4 | "AzureVaultUrl": "", 5 | "ClientId": "", 6 | "ClientSecret": "", 7 | "Thumbprint": "" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Azure Function/HttpTriggerFunctionApp/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "appInsights1": { 4 | "type": "appInsights" 5 | }, 6 | "storage1": { 7 | "type": "storage", 8 | "connectionId": "AzureWebJobsStorage" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure Function/OueueTriggeredFunctionApp/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "appInsights1": { 4 | "type": "appInsights" 5 | }, 6 | "storage1": { 7 | "type": "storage", 8 | "connectionId": "AzureWebJobsStorage" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure Function/OueueTriggeredFunctionApp/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingSettings": { 6 | "isEnabled": true, 7 | "excludedTypes": "Request" 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure Function/HttpTriggerFunctionApp/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "appInsights1": { 4 | "type": "appInsights.sdk" 5 | }, 6 | "storage1": { 7 | "type": "storage.emulator", 8 | "connectionId": "AzureWebJobsStorage" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure Function/HttpTriggerFunctionApp/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingExcludedTypes": "Request", 6 | "samplingSettings": { 7 | "isEnabled": true 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Azure Function/OueueTriggeredFunctionApp/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "appInsights1": { 4 | "type": "appInsights.sdk" 5 | }, 6 | "storage1": { 7 | "type": "storage.emulator", 8 | "connectionId": "AzureWebJobsStorage" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Service Bus Queue/AzureEventServiceBus/IEventConsumerService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace AzureEventServiceBus 5 | { 6 | public interface IEventConsumerService 7 | { 8 | Task RegisterBaseEventHandlerAsync(IList names); 9 | Task StopListenerAsync(); 10 | } 11 | } -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/IEventConsumerService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace AzureEventServiceBus 4 | { 5 | public interface IEventConsumerService 6 | { 7 | Task RegisterWeekendSubscriptionAsync(); 8 | Task RegisterWeekdaySubscriptionAsync(); 9 | Task UnSubscribeAsync(); 10 | } 11 | } -------------------------------------------------------------------------------- /Service Bus Queue/BasicEventBus/Contracts/IEvent.cs: -------------------------------------------------------------------------------- 1 | namespace BasicEventBus.Contracts 2 | { 3 | /// 4 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs 5 | /// 6 | public interface IEvent 7 | { 8 | string EventName { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/Events/SampleDemo1Event.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | 3 | namespace ServiceBusQueueAPI.Events 4 | { 5 | public class SampleDemo1Event : IEvent 6 | { 7 | public SampleDemo1Event() 8 | { 9 | EventName = GetType().Name; 10 | } 11 | 12 | public string EventName { get; set; } 13 | public string Message { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/Events/SampleDemo2Event.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | 3 | namespace ServiceBusQueueAPI.Events 4 | { 5 | public class SampleDemo2Event : IEvent 6 | { 7 | public SampleDemo2Event() 8 | { 9 | EventName = GetType().Name; 10 | } 11 | 12 | public string EventName { get; set; } 13 | public string Message { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace AzureEventServiceBus 2 | { 3 | public enum SubscriptionNames 4 | { 5 | weekend, 6 | weekday 7 | } 8 | 9 | public enum SubscriptionFilterKeys 10 | { 11 | Day 12 | } 13 | 14 | public class Constants 15 | { 16 | public const string TopicName = "azureservicetopic"; 17 | public const string ConnectionString = ""; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/Events/SampleDemoEvent.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceBusQueueAPI.Events 2 | { 3 | public interface IEvent 4 | { 5 | string EventName { get; set; } 6 | } 7 | 8 | public class SampleDemoEvent : IEvent 9 | { 10 | public SampleDemoEvent() 11 | { 12 | EventName = GetType().Name; 13 | } 14 | 15 | public string EventName { get; set; } 16 | public string Message { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/BasicEventBus/Contracts/IEvent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace BasicEventBus.Contracts 4 | { 5 | /// 6 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs 7 | /// 8 | public interface IEvent 9 | { 10 | string EventName { get; set; } 11 | IList FilterKeys { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/EventHandlers/SampleDemo1EventHandler.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using System.Threading.Tasks; 3 | 4 | namespace ServiceBusQueueAPI.Events.EventHandlers 5 | { 6 | public class SampleDemo1EventHandler : IEventHandler 7 | { 8 | public SampleDemo1EventHandler() 9 | { 10 | 11 | } 12 | 13 | public Task HandleAsync(SampleDemo1Event @event) 14 | { 15 | return Task.CompletedTask; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/EventHandlers/SampleDemo2EventHandler.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using System.Threading.Tasks; 3 | 4 | namespace ServiceBusQueueAPI.Events.EventHandlers 5 | { 6 | public class SampleDemo2EventHandler : IEventHandler 7 | { 8 | public SampleDemo2EventHandler() 9 | { 10 | 11 | } 12 | 13 | public Task HandleAsync(SampleDemo2Event @event) 14 | { 15 | return Task.CompletedTask; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/ServiceBusQueueAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/EventHandlers/WeekdaySubscriptionHandler.cs: -------------------------------------------------------------------------------- 1 | using AzureEventServiceBus.Events; 2 | using BasicEventBus.Contracts; 3 | using System.Threading.Tasks; 4 | 5 | namespace ServiceBusTopicsAPI.Events.EventHandlers 6 | { 7 | public class WeekdaySubscriptionHandler : IEventHandler 8 | { 9 | public WeekdaySubscriptionHandler() 10 | { 11 | 12 | } 13 | 14 | public Task HandleAsync(TodoTaskCreatedEvent @event) 15 | { 16 | return Task.CompletedTask; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/EventHandlers/WeekendSubscriptionHandler.cs: -------------------------------------------------------------------------------- 1 | using AzureEventServiceBus.Events; 2 | using BasicEventBus.Contracts; 3 | using System.Threading.Tasks; 4 | 5 | namespace ServiceBusTopicsAPI.Events.EventHandlers 6 | { 7 | public class WeekendSubscriptionHandler : IEventHandler 8 | { 9 | public WeekendSubscriptionHandler() 10 | { 11 | 12 | } 13 | 14 | public Task HandleAsync(TodoTaskCreatedEvent @event) 15 | { 16 | return Task.CompletedTask; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/BasicEventBus/Contracts/IEventBusService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace BasicEventBus.Contracts 4 | { 5 | /// 6 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs 7 | /// 8 | public interface IEventBusService 9 | { 10 | Task Publish(T @event) where T : class, IEvent; 11 | 12 | void Subscribe(string subscriptionName) where T : IEvent 13 | where TH : IEventHandler; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/ServiceBusTopicsAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace ServiceBusQueueAPI 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace ServiceBusTopicsAPI 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/Events/TodoTaskCreatedEvent.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using System.Collections.Generic; 3 | 4 | namespace AzureEventServiceBus.Events 5 | { 6 | public class TodoTaskCreatedEvent : IEvent 7 | { 8 | public TodoTaskCreatedEvent() 9 | { 10 | EventName = GetType().Name; 11 | FilterKeys = new List 12 | { 13 | nameof(Day) 14 | }; 15 | } 16 | 17 | public IList FilterKeys { get; set; } 18 | public string EventName { get; set; } 19 | public string Message { get; set; } 20 | public string Day { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Service Bus Queue/AzureEventServiceBus/AzureEventServiceBus.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/AzureEventServiceBus.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Azure Function/HttpTriggerFunctionApp/HttpTriggerFunctionApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp3.0 4 | v3 5 | 6 | 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | PreserveNewest 15 | Never 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Service Bus Queue/BasicEventBus/Contracts/IEventBusService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace BasicEventBus.Contracts 4 | { 5 | /// 6 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs 7 | /// 8 | public interface IEventBusService 9 | { 10 | Task Publish(T eventMessage) where T : class, IEvent; 11 | 12 | void Subscribe() where T : IEvent 13 | where TH : IEventHandler; 14 | 15 | //void Unsubscribe() where T : IBaseEvent 16 | // where TH : IBaseEventHandler; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Service Bus Queue/BasicEventBus/Contracts/IEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace BasicEventBus.Contracts 4 | { 5 | /// 6 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs 7 | /// 8 | /// 9 | public interface IEventHandler : IIntegrationEventHandler 10 | where BaseEventType : IEvent 11 | { 12 | Task HandleAsync(BaseEventType @event); 13 | } 14 | 15 | public interface IIntegrationEventHandler 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/BasicEventBus/Contracts/IEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace BasicEventBus.Contracts 4 | { 5 | /// 6 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs 7 | /// 8 | /// 9 | public interface IEventHandler : IIntegrationEventHandler 10 | where BaseEventType : IEvent 11 | { 12 | Task HandleAsync(BaseEventType @event); 13 | } 14 | 15 | public interface IIntegrationEventHandler 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/ServiceBusQueueAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Azure Function/OueueTriggeredFunctionApp/OueueTriggeredFunctionApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp3.1 4 | v3 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | PreserveNewest 13 | 14 | 15 | PreserveNewest 16 | Never 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/BasicEventBus/Contracts/IEventBusSubscriptionsManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace BasicEventBus.Contracts 5 | { 6 | /// 7 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/IEventBusSubscriptionsManager.cs 8 | /// 9 | public interface IEventBusSubscriptionsManager 10 | { 11 | void AddSubscription(string subscriptionName) where T : IEvent 12 | where TH : IEventHandler; 13 | IEnumerable GetHandlersForEvent(string subscriptionName) where T : IEvent; 14 | IEnumerable GetHandlersForEvent(string eventName, string subscriptionName); 15 | Type GetEventTypeByName(string eventName); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Mvc; 3 | using ServiceBusQueueAPI.Events; 4 | 5 | namespace ServiceBusQueueAPI.Controllers 6 | { 7 | [ApiController] 8 | [Route("[controller]")] 9 | public class HomeController : ControllerBase 10 | { 11 | private readonly IEventBusService eventBusService; 12 | 13 | public HomeController(IEventBusService eventPublisherService) 14 | { 15 | this.eventBusService = eventPublisherService; 16 | } 17 | 18 | [HttpPost("message")] 19 | public IActionResult Post(string message) 20 | { 21 | eventBusService.Publish(new SampleDemoEvent 22 | { 23 | Message = message 24 | }); 25 | return StatusCode(StatusCodes.Status200OK); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:60737", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "ServiceBusQueueAPI": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": "true", 23 | "launchBrowser": true, 24 | "launchUrl": "swagger", 25 | "applicationUrl": "http://localhost:5000", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:60737", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "ServiceBusQueueAPI": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": "true", 23 | "launchBrowser": true, 24 | "launchUrl": "swagger", 25 | "applicationUrl": "http://localhost:5000", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:60737", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "ServiceBusTopicsAPI": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": "true", 23 | "launchBrowser": true, 24 | "launchUrl": "swagger", 25 | "applicationUrl": "http://localhost:5000", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.AspNetCore.Mvc; 4 | using ServiceBusQueueAPI.Events; 5 | 6 | namespace ServiceBusQueueAPI.Controllers 7 | { 8 | [ApiController] 9 | [Route("[controller]")] 10 | public class HomeController : ControllerBase 11 | { 12 | private readonly IEventBusService eventBusService; 13 | 14 | public HomeController(IEventBusService eventPublisherService) 15 | { 16 | this.eventBusService = eventPublisherService; 17 | } 18 | 19 | [HttpPost("message")] 20 | public IActionResult Post(string message) 21 | { 22 | eventBusService.Publish( 23 | new SampleDemo1Event 24 | { 25 | Message = message 26 | }); 27 | return StatusCode(StatusCodes.Status200OK); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Azure Function/OueueTriggeredFunctionApp/Function1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.WebJobs; 2 | using Microsoft.Extensions.Logging; 3 | using Newtonsoft.Json; 4 | 5 | namespace OueueTriggeredFunctionApp 6 | { 7 | public static class Function1 8 | { 9 | [FunctionName("Function1")] 10 | [return: ServiceBus("servicebusqueueapi.events.sampledemo2event", Connection = "ServiceBusConnection")] 11 | public static string Run([ServiceBusTrigger("servicebusqueueapi.events.sampledemo1event", Connection = "ServiceBusConnection")] string myQueueItem, ILogger log) 12 | { 13 | log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}"); 14 | 15 | dynamic data = JsonConvert.DeserializeObject(myQueueItem); 16 | data.Message = "From Azure Function:" + data?.Message; 17 | data.EventName = "SampleDemo2Event"; 18 | 19 | return JsonConvert.SerializeObject(data); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/Events/EventBusService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.ServiceBus; 2 | using System.Text; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | 6 | namespace ServiceBusQueueAPI.Events 7 | { 8 | public interface IEventBusService 9 | { 10 | Task Publish(T eventMessage); 11 | } 12 | 13 | public class EventBusService : IEventBusService 14 | { 15 | private readonly string ConnectionString; 16 | 17 | public EventBusService(string connectionString) 18 | { 19 | ConnectionString = connectionString; 20 | } 21 | 22 | public async Task Publish(T eventMessage) 23 | { 24 | var queueClient = new QueueClient(ConnectionString, typeof(T).FullName); 25 | string messageBody = JsonSerializer.Serialize(eventMessage); 26 | var message = new Message(Encoding.UTF8.GetBytes(messageBody)); 27 | await queueClient.SendAsync(message); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Computer Vision POC/README.md: -------------------------------------------------------------------------------- 1 | # Analyze an Image: 2 | 3 | This example detects faces in a remote image, gets their gender and age with bounding boxes also describe the objects 4 | 5 | ``` 6 | COMPUTER_VISION_ENDPOINT + "vision/v3.1/analyze" 7 | ``` 8 | 9 | # Detect object in a Image: 10 | 11 | This example detects different kinds of objects with bounding boxes in a image 12 | 13 | ``` 14 | COMPUTER_VISION_ENDPOINT + "vision/v3.1/detect" 15 | ``` 16 | 17 | # Describe an Image: 18 | 19 | This API describes the image with the confidence score. 20 | 21 | ``` 22 | COMPUTER_VISION_ENDPOINT + "vision/v3.1/describe" 23 | ``` 24 | 25 | **Image used for MS OCR API** 26 | 27 | 28 | 29 | **Image used for analyze, detect & describe API** 30 | 31 | 32 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using AzureEventServiceBus.Events; 2 | using BasicEventBus.Contracts; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace ServiceBusTopicsAPI.Controllers 7 | { 8 | [ApiController] 9 | [Route("[controller]")] 10 | public class HomeController : ControllerBase 11 | { 12 | private readonly IEventBusService eventBusService; 13 | 14 | public HomeController(IEventBusService eventPublisherService) 15 | { 16 | this.eventBusService = eventPublisherService; 17 | } 18 | 19 | [HttpPost("{message}/{day}")] 20 | public IActionResult Post(string message, Days day) 21 | { 22 | var @event = new TodoTaskCreatedEvent 23 | { 24 | Day = day.ToString(), 25 | Message = message, 26 | }; 27 | eventBusService.Publish(@event); 28 | return StatusCode(StatusCodes.Status200OK); 29 | } 30 | } 31 | 32 | public enum Days { Sunday, Saturday, Otherday } 33 | } 34 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/HostedBackgroundService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace AzureEventServiceBus 6 | { 7 | /// 8 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/master/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs 9 | /// 10 | public class HostedBackgroundService : IHostedService 11 | { 12 | private readonly IEventConsumerService _serviceBusConsumer; 13 | 14 | public HostedBackgroundService(IEventConsumerService serviceBusConsumer) 15 | { 16 | _serviceBusConsumer = serviceBusConsumer; 17 | } 18 | 19 | public async Task StartAsync(CancellationToken cancellationToken) 20 | { 21 | await _serviceBusConsumer.RegisterWeekendSubscriptionAsync(); 22 | await _serviceBusConsumer.RegisterWeekdaySubscriptionAsync(); 23 | } 24 | 25 | public async Task StopAsync(CancellationToken cancellationToken) 26 | { 27 | await _serviceBusConsumer.UnSubscribeAsync(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/AzureVaultConfiguration/PrefixKeyVaultSecretManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.KeyVault.Models; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Configuration.AzureKeyVault; 4 | 5 | namespace ServiceBusQueueAPI.AzureVaultConfiguration 6 | { 7 | /// 8 | /// https://docs.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-5.0#use-a-key-name-prefix 9 | /// 10 | public class PrefixKeyVaultSecretManager : IKeyVaultSecretManager 11 | { 12 | private readonly string _prefix; 13 | 14 | public PrefixKeyVaultSecretManager(string prefix) 15 | { 16 | _prefix = $"{prefix}-"; 17 | } 18 | 19 | public string GetKey(SecretBundle secret) 20 | { 21 | return secret.SecretIdentifier 22 | .Name 23 | .Substring(_prefix.Length) 24 | .Replace("--", ConfigurationPath.KeyDelimiter); 25 | } 26 | 27 | public bool Load(SecretItem secret) 28 | { 29 | return secret.Identifier.Name.StartsWith(_prefix); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/AzureVaultConfiguration/AzureKeyVaultCertificationExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography.X509Certificates; 3 | 4 | namespace ServiceBusQueueAPI.AzureVaultConfiguration 5 | { 6 | public class AzureKeyVaultCertificationExtension 7 | { 8 | public static X509Certificate2 FindCertificateByThumbprint(string thumbprint) 9 | { 10 | X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 11 | try 12 | { 13 | store.Open(OpenFlags.ReadOnly); 14 | X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); 15 | if (certificates?.Count == 0) 16 | { 17 | throw new Exception("Error: Certificate not found!"); 18 | } 19 | return certificates[0]; 20 | } 21 | catch (Exception ex) 22 | { 23 | Console.WriteLine(ex.Message); 24 | return null; 25 | } 26 | finally 27 | { 28 | store.Close(); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Service Bus Queue/BasicEventBus/Contracts/IEventBusSubscriptionsManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace BasicEventBus.Contracts 5 | { 6 | /// 7 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/IEventBusSubscriptionsManager.cs 8 | /// 9 | public interface IEventBusSubscriptionsManager 10 | { 11 | void AddSubscription() where T : IEvent 12 | where TH : IEventHandler; 13 | IEnumerable GetHandlersForEvent() where T : IEvent; 14 | IEnumerable GetHandlersForEvent(string eventName); 15 | Type GetEventTypeByName(string eventName); 16 | 17 | //bool IsEmpty { get; } 18 | //event EventHandler OnEventRemoved; 19 | //void RemoveSubscription() where TH : IBaseEventHandler 20 | // where T : IBaseEvent; 21 | //bool HasSubscriptionsForEvent() where T : IBaseEvent; 22 | //bool HasSubscriptionsForEvent(string eventName); 23 | //void Clear(); 24 | 25 | //string GetEventKey(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Service Bus Queue/AzureEventServiceBus/HostedBackgroundService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace AzureEventServiceBus 7 | { 8 | /// 9 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/master/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs 10 | /// 11 | public class HostedBackgroundService : IHostedService 12 | { 13 | private readonly IEventConsumerService _serviceBusConsumer; 14 | private readonly IList names; 15 | 16 | public HostedBackgroundService(IEventConsumerService serviceBusConsumer, IList names) 17 | { 18 | _serviceBusConsumer = serviceBusConsumer; 19 | this.names = names; 20 | } 21 | 22 | public async Task StartAsync(CancellationToken cancellationToken) 23 | { 24 | await _serviceBusConsumer.RegisterBaseEventHandlerAsync(names); 25 | } 26 | 27 | public async Task StopAsync(CancellationToken cancellationToken) 28 | { 29 | await _serviceBusConsumer.StopListenerAsync(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueWithAzureKeyVault.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31019.35 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceBusQueueAPI", "ServiceBusQueueAPI\ServiceBusQueueAPI.csproj", "{5503E05A-5D3A-4A02-94CF-BAA33CCA076C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5503E05A-5D3A-4A02-94CF-BAA33CCA076C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {5503E05A-5D3A-4A02-94CF-BAA33CCA076C}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {5503E05A-5D3A-4A02-94CF-BAA33CCA076C}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {5503E05A-5D3A-4A02-94CF-BAA33CCA076C}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {837B514C-0E77-45C6-8F02-6BF3783E16F2} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Azure Function/HttpTriggerFunctionApp/Function1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Azure.WebJobs; 4 | using Microsoft.Azure.WebJobs.Extensions.Http; 5 | using Microsoft.Extensions.Logging; 6 | using Newtonsoft.Json; 7 | using System.IO; 8 | using System.Threading.Tasks; 9 | 10 | namespace HttpTriggerFunctionApp 11 | { 12 | public static class Function1 13 | { 14 | [FunctionName("Function1")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log) 17 | { 18 | log.LogInformation("C# HTTP trigger function processed a request."); 19 | 20 | string name = req.Query["name"]; 21 | 22 | string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); 23 | dynamic data = JsonConvert.DeserializeObject(requestBody); 24 | name = name ?? data?.name; 25 | 26 | string responseMessage = string.IsNullOrEmpty(name) 27 | ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response." 28 | : $"Hello, {name}. This HTTP triggered function executed successfully."; 29 | 30 | return new OkObjectResult(responseMessage); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Service Bus Queue/AzureEventServiceBus/EventBusService.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using Microsoft.Azure.ServiceBus; 3 | using System.Text; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | 7 | namespace AzureEventServiceBus 8 | { 9 | /// 10 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/master/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs 11 | /// 12 | public class EventBusService : IEventBusService 13 | { 14 | private readonly IEventBusSubscriptionsManager _eventBusSubscriptionsManager; 15 | private readonly string ConnectionString = ""; 16 | 17 | public EventBusService(IEventBusSubscriptionsManager eventBusSubscriptionsManager) 18 | { 19 | this._eventBusSubscriptionsManager = eventBusSubscriptionsManager; 20 | } 21 | 22 | public void Subscribe() 23 | where T : IEvent 24 | where TH : IEventHandler 25 | { 26 | _eventBusSubscriptionsManager.AddSubscription(); 27 | } 28 | 29 | async Task IEventBusService.Publish(T eventMessage) 30 | { 31 | var queueClient = new QueueClient(ConnectionString, typeof(T).FullName); 32 | string messageBody = JsonSerializer.Serialize(eventMessage); 33 | var message = new Message(Encoding.UTF8.GetBytes(messageBody)); 34 | await queueClient.SendAsync(message); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Azure Function/Azure Function.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31019.35 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpTriggerFunctionApp", "HttpTriggerFunctionApp\HttpTriggerFunctionApp.csproj", "{4C246944-601C-4AC3-96D7-23DCE08D1065}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OueueTriggeredFunctionApp", "OueueTriggeredFunctionApp\OueueTriggeredFunctionApp.csproj", "{BD69D9EC-28D2-4ED5-9A7D-B2778F2E912C}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4C246944-601C-4AC3-96D7-23DCE08D1065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {4C246944-601C-4AC3-96D7-23DCE08D1065}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {4C246944-601C-4AC3-96D7-23DCE08D1065}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {4C246944-601C-4AC3-96D7-23DCE08D1065}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {BD69D9EC-28D2-4ED5-9A7D-B2778F2E912C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {BD69D9EC-28D2-4ED5-9A7D-B2778F2E912C}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {BD69D9EC-28D2-4ED5-9A7D-B2778F2E912C}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {BD69D9EC-28D2-4ED5-9A7D-B2778F2E912C}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {2EBC7711-2153-4B89-B281-136CC1E76E59} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/EventBusService.cs: -------------------------------------------------------------------------------- 1 | using Azure.Messaging.ServiceBus; 2 | using BasicEventBus.Contracts; 3 | using System; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | 7 | namespace AzureEventServiceBus 8 | { 9 | /// 10 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/master/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs 11 | /// 12 | public class EventBusService : IEventBusService 13 | { 14 | private readonly IEventBusSubscriptionsManager _eventBusSubscriptionsManager; 15 | private readonly ServiceBusSender _clientSender; 16 | 17 | public EventBusService(IEventBusSubscriptionsManager eventBusSubscriptionsManager) 18 | { 19 | this._eventBusSubscriptionsManager = eventBusSubscriptionsManager; 20 | var client = new ServiceBusClient(Constants.ConnectionString); 21 | _clientSender = client.CreateSender(Constants.TopicName); 22 | } 23 | 24 | public void Subscribe(string subscriptionName) 25 | where T : IEvent 26 | where TH : IEventHandler 27 | { 28 | _eventBusSubscriptionsManager.AddSubscription(subscriptionName); 29 | } 30 | 31 | async Task IEventBusService.Publish(T @event) 32 | { 33 | try 34 | { 35 | string eventMessage = JsonSerializer.Serialize(@event); 36 | ServiceBusMessage message = new ServiceBusMessage(eventMessage); 37 | 38 | foreach (var key in @event.FilterKeys) 39 | { 40 | var d = @event.GetType().GetProperty(key).GetValue(@event); 41 | message.ApplicationProperties.Add(key, d); 42 | } 43 | 44 | await _clientSender.SendMessageAsync(message); 45 | } 46 | catch (Exception ex) 47 | { 48 | Console.WriteLine(ex.Message); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.OpenApi.Models; 7 | using ServiceBusQueueAPI.Events; 8 | 9 | namespace ServiceBusQueueAPI 10 | { 11 | /// 12 | /// Manage user secrets 13 | /// https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows 14 | /// 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | 28 | services.AddControllers(); 29 | services.AddSwaggerGen(c => 30 | { 31 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "ServiceBusQueueAPI", Version = "v1" }); 32 | }); 33 | 34 | services.AddSingleton(ServiceProvider => 35 | { 36 | var connectionString = Configuration.GetSection("Configuration:ConnectionString").Value; 37 | return new EventBusService(connectionString); 38 | }); 39 | } 40 | 41 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 42 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 43 | { 44 | if (env.IsDevelopment()) 45 | { 46 | app.UseDeveloperExceptionPage(); 47 | app.UseSwagger(); 48 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServiceBusQueueAPI v1")); 49 | } 50 | 51 | app.UseRouting(); 52 | 53 | app.UseAuthorization(); 54 | 55 | app.UseEndpoints(endpoints => 56 | { 57 | endpoints.MapControllers(); 58 | }); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueue.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31019.35 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceBusQueueAPI", "ServiceBusQueueAPI\ServiceBusQueueAPI.csproj", "{D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureEventServiceBus", "AzureEventServiceBus\AzureEventServiceBus.csproj", "{0377B559-3B96-46C9-B23E-715AF8DAE92E}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicEventBus", "BasicEventBus\BasicEventBus.csproj", "{C2FF3BA8-B435-4DBC-B76D-28647A3099F9}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {837B514C-0E77-45C6-8F02-6BF3783E16F2} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopics.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31019.35 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceBusTopicsAPI", "ServiceBusTopicsAPI\ServiceBusTopicsAPI.csproj", "{D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureEventServiceBus", "AzureEventServiceBus\AzureEventServiceBus.csproj", "{0377B559-3B96-46C9-B23E-715AF8DAE92E}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicEventBus", "BasicEventBus\BasicEventBus.csproj", "{C2FF3BA8-B435-4DBC-B76D-28647A3099F9}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {D9AA5018-A39B-4C4E-8D37-7B65554B1F3E}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {0377B559-3B96-46C9-B23E-715AF8DAE92E}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {C2FF3BA8-B435-4DBC-B76D-28647A3099F9}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {837B514C-0E77-45C6-8F02-6BF3783E16F2} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Azure Key Vault/ServiceBusQueueAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace ServiceBusQueueAPI 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | 16 | //Using ClienId and Client Secret 17 | 18 | //.ConfigureAppConfiguration((context, config) => 19 | //{ 20 | // var builtConfig = config.Build(); 21 | // var azureVaultUrl = builtConfig.GetSection("Configuration:AzureVaultUrl").Value; 22 | // var clientId = builtConfig.GetSection("Configuration:ClientId").Value; 23 | // var clientSecret = builtConfig.GetSection("Configuration:ClientSecret").Value; 24 | // config.AddAzureKeyVault(azureVaultUrl, clientId, clientSecret, 25 | // new PrefixKeyVaultSecretManager("ServiceBusQueueAPI")); 26 | //}) 27 | 28 | //+-+-+-+-+-+-+-+-+-+- Uncomment one of the option -+-+-+-+-+-+-+-+-+ 29 | 30 | //Using ClienId and Certificate Thumb print 31 | 32 | //.ConfigureAppConfiguration((context, config) => 33 | //{ 34 | 35 | // var builtConfig = config.Build(); 36 | // var azureVaultUrl = builtConfig.GetSection("Configuration:AzureVaultUrl").Value; 37 | // var clientId = builtConfig.GetSection("Configuration:ClientId").Value; 38 | // var thumbprint = builtConfig.GetSection("Configuration:Thumbprint").Value; 39 | // config.AddAzureKeyVault( 40 | // azureVaultUrl, 41 | // clientId, 42 | // AzureKeyVaultCertificationExtension.FindCertificateByThumbprint(thumbprint), 43 | // new PrefixKeyVaultSecretManager("ServiceBusQueueAPI")); 44 | //}) 45 | .ConfigureWebHostDefaults(webBuilder => 46 | { 47 | webBuilder.UseStartup(); 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Service Bus Queue/BasicEventBus/EventBusSubscriptionsManager.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace BasicEventBus 8 | { 9 | /// 10 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs 11 | /// 12 | public class EventBusSubscriptionsManager : IEventBusSubscriptionsManager 13 | { 14 | private readonly ConcurrentDictionary> _handlers; 15 | private ConcurrentBag _eventTypes; 16 | public EventBusSubscriptionsManager() 17 | { 18 | _handlers = new ConcurrentDictionary>(); 19 | _eventTypes = new ConcurrentBag(); 20 | } 21 | 22 | public void AddSubscription() 23 | where T : IEvent 24 | where TH : IEventHandler 25 | { 26 | var eventName = GetEventKey(); 27 | 28 | DoAddSubscription(typeof(TH), eventName); 29 | _eventTypes.Add(typeof(T)); 30 | } 31 | 32 | private void DoAddSubscription(Type handlerType, string eventName) 33 | { 34 | if (_handlers.ContainsKey(eventName) && _handlers[eventName].Any(s => s == handlerType)) 35 | { 36 | throw new ArgumentException( 37 | $"Handler Type {handlerType.Name} already registered for '{eventName}'", nameof(handlerType)); 38 | } 39 | 40 | _handlers.AddOrUpdate(eventName, 41 | x => new List() { handlerType }, 42 | (k, v) => 43 | { 44 | v.Add(handlerType); 45 | return v; 46 | }); 47 | } 48 | 49 | public IEnumerable GetHandlersForEvent() where T : IEvent 50 | { 51 | var key = GetEventKey(); 52 | return GetHandlersForEvent(key); 53 | } 54 | public IEnumerable GetHandlersForEvent(string eventName) => _handlers[eventName]; 55 | 56 | public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); 57 | 58 | public string GetEventKey() 59 | { 60 | return typeof(T).Name; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/BasicEventBus/EventBusSubscriptionsManager.cs: -------------------------------------------------------------------------------- 1 | using BasicEventBus.Contracts; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace BasicEventBus 8 | { 9 | /// 10 | /// https://github.com/dotnet-architecture/eShopOnContainers/blob/dotnet3-migration/dev-dotnet3/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs 11 | /// 12 | public class EventBusSubscriptionsManager : IEventBusSubscriptionsManager 13 | { 14 | private readonly ConcurrentDictionary> _handlers; 15 | private ConcurrentBag _eventTypes; 16 | public EventBusSubscriptionsManager() 17 | { 18 | _handlers = new ConcurrentDictionary>(); 19 | _eventTypes = new ConcurrentBag(); 20 | } 21 | 22 | public void AddSubscription(string subscriptionName) 23 | where T : IEvent 24 | where TH : IEventHandler 25 | { 26 | var eventName = GetEventKey(); 27 | 28 | DoAddSubscription(typeof(TH), GetHandlerKey(eventName, subscriptionName)); 29 | _eventTypes.Add(typeof(T)); 30 | } 31 | 32 | private static string GetHandlerKey(string eventName, string subscriptionName) 33 | { 34 | return $"{eventName}_{subscriptionName}"; 35 | } 36 | 37 | private void DoAddSubscription(Type handlerType, string handlerKey) 38 | { 39 | if (_handlers.ContainsKey(handlerKey) && _handlers[handlerKey].Any(s => s == handlerType)) 40 | { 41 | throw new ArgumentException( 42 | $"Handler Type {handlerType.Name} already registered for '{handlerKey}'", nameof(handlerType)); 43 | } 44 | 45 | _handlers.AddOrUpdate(handlerKey, 46 | x => new List() { handlerType }, 47 | (k, v) => 48 | { 49 | v.Add(handlerType); 50 | return v; 51 | }); 52 | } 53 | 54 | public IEnumerable GetHandlersForEvent(string subscriptionName) where T : IEvent 55 | { 56 | var eventName = GetEventKey(); 57 | return GetHandlersForEvent(eventName, subscriptionName); 58 | } 59 | 60 | public IEnumerable GetHandlersForEvent(string eventName, string subscriptionName) 61 | => _handlers[GetHandlerKey(eventName, subscriptionName)]; 62 | 63 | public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); 64 | 65 | public string GetEventKey() 66 | { 67 | return typeof(T).Name; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/ServiceBusTopicsAPI/Startup.cs: -------------------------------------------------------------------------------- 1 | using AzureEventServiceBus; 2 | using AzureEventServiceBus.Events; 3 | using BasicEventBus; 4 | using BasicEventBus.Contracts; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.OpenApi.Models; 11 | using Newtonsoft.Json.Converters; 12 | using ServiceBusTopicsAPI.Events.EventHandlers; 13 | 14 | namespace ServiceBusTopicsAPI 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | 29 | // https://stackoverflow.com/a/55541764/1175623 30 | services.AddControllers().AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(new StringEnumConverter())); 31 | services.AddSwaggerGenNewtonsoftSupport(); 32 | 33 | services.AddControllers(); 34 | services.AddControllers(); 35 | services.AddSwaggerGen(c => 36 | { 37 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "ServiceBusTopicsAPI", Version = "v1" }); 38 | }); 39 | RegisterServices(services); 40 | AddEventHandlers(services); 41 | } 42 | 43 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 44 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 45 | { 46 | if (env.IsDevelopment()) 47 | { 48 | app.UseDeveloperExceptionPage(); 49 | app.UseSwagger(); 50 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServiceBusTopicsAPI v1")); 51 | } 52 | 53 | BindAzureTopicSubscription(app); 54 | 55 | app.UseRouting(); 56 | 57 | app.UseAuthorization(); 58 | 59 | app.UseEndpoints(endpoints => 60 | { 61 | endpoints.MapControllers(); 62 | }); 63 | } 64 | 65 | #region Event Consumer 66 | 67 | private void RegisterServices(IServiceCollection services) 68 | { 69 | services.AddSingleton(); 70 | services.AddSingleton(); 71 | services.AddSingleton(); 72 | services.AddSingleton(); 73 | } 74 | 75 | private void BindAzureTopicSubscription(IApplicationBuilder app) 76 | { 77 | var eventBus = app.ApplicationServices.GetRequiredService(); 78 | 79 | eventBus.Subscribe(SubscriptionNames.weekday.ToString()); 80 | 81 | eventBus.Subscribe(SubscriptionNames.weekend.ToString()); 82 | } 83 | 84 | public void AddEventHandlers(IServiceCollection services) 85 | { 86 | services.AddTransient(); 87 | services.AddTransient(); 88 | } 89 | 90 | #endregion Event Consumer 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Service Bus Queue/ServiceBusQueueAPI/Startup.cs: -------------------------------------------------------------------------------- 1 | using AzureEventServiceBus; 2 | using BasicEventBus; 3 | using BasicEventBus.Contracts; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | using Microsoft.OpenApi.Models; 10 | using ServiceBusQueueAPI.Events; 11 | using ServiceBusQueueAPI.Events.EventHandlers; 12 | using System.Collections.Generic; 13 | 14 | namespace ServiceBusQueueAPI 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | 29 | services.AddControllers(); 30 | services.AddSwaggerGen(c => 31 | { 32 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "ServiceBusQueueAPI", Version = "v1" }); 33 | }); 34 | RegisterServices(services); 35 | AddEventHandlers(services); 36 | } 37 | 38 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 39 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 40 | { 41 | if (env.IsDevelopment()) 42 | { 43 | app.UseDeveloperExceptionPage(); 44 | app.UseSwagger(); 45 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServiceBusQueueAPI v1")); 46 | } 47 | 48 | ConfigureEventBus(app); 49 | 50 | app.UseRouting(); 51 | 52 | app.UseAuthorization(); 53 | 54 | app.UseEndpoints(endpoints => 55 | { 56 | endpoints.MapControllers(); 57 | }); 58 | } 59 | 60 | #region Event Consumer 61 | 62 | private void RegisterServices(IServiceCollection services) 63 | { 64 | services.AddSingleton(); 65 | services.AddSingleton(); 66 | services.AddSingleton(); 67 | services.AddSingleton(sp => 68 | { 69 | var baseEventServiceBus = sp.GetRequiredService(); 70 | return new HostedBackgroundService(baseEventServiceBus, GetEventOrQueueNames()); 71 | }); 72 | } 73 | 74 | private void ConfigureEventBus(IApplicationBuilder app) 75 | { 76 | var eventBus = app.ApplicationServices.GetRequiredService(); 77 | //eventBus.Subscribe(); 78 | eventBus.Subscribe(); 79 | } 80 | 81 | public void AddEventHandlers(IServiceCollection services) 82 | { 83 | services.AddTransient(); 84 | services.AddTransient(); 85 | } 86 | 87 | private List GetEventOrQueueNames() 88 | { 89 | return new List 90 | { 91 | typeof(SampleDemo1Event).FullName, 92 | typeof(SampleDemo2Event).FullName 93 | }; 94 | } 95 | 96 | #endregion Event Consumer 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Service Bus Queue/AzureEventServiceBus/EventConsumerService.cs: -------------------------------------------------------------------------------- 1 | using Azure.Messaging.ServiceBus; 2 | using BasicEventBus.Contracts; 3 | using Newtonsoft.Json; 4 | using Newtonsoft.Json.Linq; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace AzureEventServiceBus 12 | { 13 | public class EventConsumerService : IEventConsumerService 14 | { 15 | private readonly ServiceBusClient _client; 16 | private List _processors = new List(); 17 | private readonly IServiceProvider _serviceProvider; 18 | private readonly IEventBusSubscriptionsManager _eventBusSubscriptionsManager; 19 | 20 | public EventConsumerService(IServiceProvider serviceProvider, IEventBusSubscriptionsManager eventBusSubscriptionsManager) 21 | { 22 | // this can be set from appsettings 23 | var connectionString = ""; 24 | _client = new ServiceBusClient(connectionString); 25 | this._serviceProvider = serviceProvider; 26 | _eventBusSubscriptionsManager = eventBusSubscriptionsManager; 27 | } 28 | 29 | public async Task StopListenerAsync() 30 | { 31 | _processors.ForEach(async p => 32 | { 33 | await p.CloseAsync(); 34 | }); 35 | await _client.DisposeAsync(); 36 | } 37 | 38 | public async Task RegisterBaseEventHandlerAsync(IList names) 39 | { 40 | if (names == null || !names.Any()) return; 41 | 42 | ServiceBusProcessorOptions serviceBusProcessorOptions = new ServiceBusProcessorOptions 43 | { AutoCompleteMessages = false }; 44 | 45 | foreach (var name in names) 46 | { 47 | var processors = _client.CreateProcessor(name, serviceBusProcessorOptions); 48 | processors.ProcessMessageAsync += ProcessMessagesAsync; 49 | processors.ProcessErrorAsync += ProcessErrorAsync; 50 | await processors.StartProcessingAsync(); 51 | _processors.Add(processors); 52 | } 53 | } 54 | 55 | private async Task ProcessMessagesAsync(ProcessMessageEventArgs arg) 56 | { 57 | string jsonString = Encoding.UTF8.GetString(arg.Message.Body); 58 | dynamic data = JObject.Parse(jsonString); 59 | var eventName = data.EventName?.ToString(); 60 | 61 | var messageEventType = _eventBusSubscriptionsManager.GetEventTypeByName(eventName); 62 | dynamic deserialized = JsonConvert.DeserializeObject(jsonString, messageEventType); 63 | 64 | 65 | var handlerTypes = _eventBusSubscriptionsManager.GetHandlersForEvent(eventName); 66 | foreach (var handlerType in handlerTypes) 67 | { 68 | dynamic handlerInstance = _serviceProvider.GetService(handlerType); 69 | // http://techxposer.com/2018/01/03/missing-compiler-required-member-microsoft-csharp-runtimebinder-csharpargumentinfo-create-solved/ 70 | // https://social.msdn.microsoft.com/Forums/sharepoint/en-US/2b855369-a721-4010-9e33-72d699960994/how-to-fix-missing-compiler-member-error-microsoftcsharpruntimebindercsharpargumentinfocreate?forum=visualstudiogeneral 71 | await handlerInstance?.HandleAsync(deserialized); 72 | } 73 | await arg.CompleteMessageAsync(arg.Message); 74 | } 75 | 76 | private Task ProcessErrorAsync(ProcessErrorEventArgs arg) 77 | { 78 | // log or do something 79 | return Task.CompletedTask; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Azure Function/HttpTriggerFunctionApp/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # Azure Functions localsettings file 5 | local.settings.json 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # DNX 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # NCrunch 117 | _NCrunch_* 118 | .*crunch*.local.xml 119 | nCrunchTemp_* 120 | 121 | # MightyMoose 122 | *.mm.* 123 | AutoTest.Net/ 124 | 125 | # Web workbench (sass) 126 | .sass-cache/ 127 | 128 | # Installshield output folder 129 | [Ee]xpress/ 130 | 131 | # DocProject is a documentation generator add-in 132 | DocProject/buildhelp/ 133 | DocProject/Help/*.HxT 134 | DocProject/Help/*.HxC 135 | DocProject/Help/*.hhc 136 | DocProject/Help/*.hhk 137 | DocProject/Help/*.hhp 138 | DocProject/Help/Html2 139 | DocProject/Help/html 140 | 141 | # Click-Once directory 142 | publish/ 143 | 144 | # Publish Web Output 145 | *.[Pp]ublish.xml 146 | *.azurePubxml 147 | # TODO: Comment the next line if you want to checkin your web deploy settings 148 | # but database connection strings (with potential passwords) will be unencrypted 149 | #*.pubxml 150 | *.publishproj 151 | 152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 153 | # checkin your Azure Web App publish settings, but sensitive information contained 154 | # in these scripts will be unencrypted 155 | PublishScripts/ 156 | 157 | # NuGet Packages 158 | *.nupkg 159 | # The packages folder can be ignored because of Package Restore 160 | **/packages/* 161 | # except build/, which is used as an MSBuild target. 162 | !**/packages/build/ 163 | # Uncomment if necessary however generally it will be regenerated when needed 164 | #!**/packages/repositories.config 165 | # NuGet v3's project.json files produces more ignoreable files 166 | *.nuget.props 167 | *.nuget.targets 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Windows Store app package directories and files 178 | AppPackages/ 179 | BundleArtifacts/ 180 | Package.StoreAssociation.xml 181 | _pkginfo.txt 182 | 183 | # Visual Studio cache files 184 | # files ending in .cache can be ignored 185 | *.[Cc]ache 186 | # but keep track of directories ending in .cache 187 | !*.[Cc]ache/ 188 | 189 | # Others 190 | ClientBin/ 191 | ~$* 192 | *~ 193 | *.dbmdl 194 | *.dbproj.schemaview 195 | *.jfm 196 | *.pfx 197 | *.publishsettings 198 | node_modules/ 199 | orleans.codegen.cs 200 | 201 | # Since there are multiple workflows, uncomment next line to ignore bower_components 202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 203 | #bower_components/ 204 | 205 | # RIA/Silverlight projects 206 | Generated_Code/ 207 | 208 | # Backup & report files from converting an old project file 209 | # to a newer Visual Studio version. Backup files are not needed, 210 | # because we have git ;-) 211 | _UpgradeReport_Files/ 212 | Backup*/ 213 | UpgradeLog*.XML 214 | UpgradeLog*.htm 215 | 216 | # SQL Server files 217 | *.mdf 218 | *.ldf 219 | 220 | # Business Intelligence projects 221 | *.rdl.data 222 | *.bim.layout 223 | *.bim_*.settings 224 | 225 | # Microsoft Fakes 226 | FakesAssemblies/ 227 | 228 | # GhostDoc plugin setting file 229 | *.GhostDoc.xml 230 | 231 | # Node.js Tools for Visual Studio 232 | .ntvs_analysis.dat 233 | 234 | # Visual Studio 6 build log 235 | *.plg 236 | 237 | # Visual Studio 6 workspace options file 238 | *.opt 239 | 240 | # Visual Studio LightSwitch build output 241 | **/*.HTMLClient/GeneratedArtifacts 242 | **/*.DesktopClient/GeneratedArtifacts 243 | **/*.DesktopClient/ModelManifest.xml 244 | **/*.Server/GeneratedArtifacts 245 | **/*.Server/ModelManifest.xml 246 | _Pvt_Extensions 247 | 248 | # Paket dependency manager 249 | .paket/paket.exe 250 | paket-files/ 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | 255 | # JetBrains Rider 256 | .idea/ 257 | *.sln.iml 258 | 259 | # CodeRush 260 | .cr/ 261 | 262 | # Python Tools for Visual Studio (PTVS) 263 | __pycache__/ 264 | *.pyc -------------------------------------------------------------------------------- /Azure Function/OueueTriggeredFunctionApp/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # Azure Functions localsettings file 5 | local.settings.json 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # DNX 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # NCrunch 117 | _NCrunch_* 118 | .*crunch*.local.xml 119 | nCrunchTemp_* 120 | 121 | # MightyMoose 122 | *.mm.* 123 | AutoTest.Net/ 124 | 125 | # Web workbench (sass) 126 | .sass-cache/ 127 | 128 | # Installshield output folder 129 | [Ee]xpress/ 130 | 131 | # DocProject is a documentation generator add-in 132 | DocProject/buildhelp/ 133 | DocProject/Help/*.HxT 134 | DocProject/Help/*.HxC 135 | DocProject/Help/*.hhc 136 | DocProject/Help/*.hhk 137 | DocProject/Help/*.hhp 138 | DocProject/Help/Html2 139 | DocProject/Help/html 140 | 141 | # Click-Once directory 142 | publish/ 143 | 144 | # Publish Web Output 145 | *.[Pp]ublish.xml 146 | *.azurePubxml 147 | # TODO: Comment the next line if you want to checkin your web deploy settings 148 | # but database connection strings (with potential passwords) will be unencrypted 149 | #*.pubxml 150 | *.publishproj 151 | 152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 153 | # checkin your Azure Web App publish settings, but sensitive information contained 154 | # in these scripts will be unencrypted 155 | PublishScripts/ 156 | 157 | # NuGet Packages 158 | *.nupkg 159 | # The packages folder can be ignored because of Package Restore 160 | **/packages/* 161 | # except build/, which is used as an MSBuild target. 162 | !**/packages/build/ 163 | # Uncomment if necessary however generally it will be regenerated when needed 164 | #!**/packages/repositories.config 165 | # NuGet v3's project.json files produces more ignoreable files 166 | *.nuget.props 167 | *.nuget.targets 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Windows Store app package directories and files 178 | AppPackages/ 179 | BundleArtifacts/ 180 | Package.StoreAssociation.xml 181 | _pkginfo.txt 182 | 183 | # Visual Studio cache files 184 | # files ending in .cache can be ignored 185 | *.[Cc]ache 186 | # but keep track of directories ending in .cache 187 | !*.[Cc]ache/ 188 | 189 | # Others 190 | ClientBin/ 191 | ~$* 192 | *~ 193 | *.dbmdl 194 | *.dbproj.schemaview 195 | *.jfm 196 | *.pfx 197 | *.publishsettings 198 | node_modules/ 199 | orleans.codegen.cs 200 | 201 | # Since there are multiple workflows, uncomment next line to ignore bower_components 202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 203 | #bower_components/ 204 | 205 | # RIA/Silverlight projects 206 | Generated_Code/ 207 | 208 | # Backup & report files from converting an old project file 209 | # to a newer Visual Studio version. Backup files are not needed, 210 | # because we have git ;-) 211 | _UpgradeReport_Files/ 212 | Backup*/ 213 | UpgradeLog*.XML 214 | UpgradeLog*.htm 215 | 216 | # SQL Server files 217 | *.mdf 218 | *.ldf 219 | 220 | # Business Intelligence projects 221 | *.rdl.data 222 | *.bim.layout 223 | *.bim_*.settings 224 | 225 | # Microsoft Fakes 226 | FakesAssemblies/ 227 | 228 | # GhostDoc plugin setting file 229 | *.GhostDoc.xml 230 | 231 | # Node.js Tools for Visual Studio 232 | .ntvs_analysis.dat 233 | 234 | # Visual Studio 6 build log 235 | *.plg 236 | 237 | # Visual Studio 6 workspace options file 238 | *.opt 239 | 240 | # Visual Studio LightSwitch build output 241 | **/*.HTMLClient/GeneratedArtifacts 242 | **/*.DesktopClient/GeneratedArtifacts 243 | **/*.DesktopClient/ModelManifest.xml 244 | **/*.Server/GeneratedArtifacts 245 | **/*.Server/ModelManifest.xml 246 | _Pvt_Extensions 247 | 248 | # Paket dependency manager 249 | .paket/paket.exe 250 | paket-files/ 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | 255 | # JetBrains Rider 256 | .idea/ 257 | *.sln.iml 258 | 259 | # CodeRush 260 | .cr/ 261 | 262 | # Python Tools for Visual Studio (PTVS) 263 | __pycache__/ 264 | *.pyc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /Service Bus Queue Topics/AzureEventServiceBus/EventConsumerService.cs: -------------------------------------------------------------------------------- 1 | using Azure.Messaging.ServiceBus; 2 | using Azure.Messaging.ServiceBus.Administration; 3 | using AzureEventServiceBus.Events; 4 | using BasicEventBus.Contracts; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | 9 | namespace AzureEventServiceBus 10 | { 11 | public class EventConsumerService : IEventConsumerService 12 | { 13 | private readonly ServiceBusClient _client; 14 | private List _processors = new List(); 15 | private readonly IServiceProvider _serviceProvider; 16 | private readonly ServiceBusAdministrationClient _adminClient; 17 | private readonly IEventBusSubscriptionsManager _eventBusSubscriptionsManager; 18 | 19 | public EventConsumerService(IServiceProvider serviceProvider, IEventBusSubscriptionsManager eventBusSubscriptionsManager) 20 | { 21 | _client = new ServiceBusClient(Constants.ConnectionString); 22 | this._serviceProvider = serviceProvider; 23 | _eventBusSubscriptionsManager = eventBusSubscriptionsManager; 24 | _adminClient = new ServiceBusAdministrationClient(Constants.ConnectionString); 25 | } 26 | 27 | public async Task UnSubscribeAsync() 28 | { 29 | _processors.ForEach(async p => 30 | { 31 | await p.CloseAsync(); 32 | }); 33 | await _client.DisposeAsync(); 34 | } 35 | 36 | public async Task RegisterWeekendSubscriptionAsync() 37 | { 38 | ServiceBusProcessorOptions serviceBusProcessorOptions = new ServiceBusProcessorOptions 39 | { AutoCompleteMessages = false }; 40 | 41 | var processors = _client.CreateProcessor(Constants.TopicName, SubscriptionNames.weekend.ToString(), serviceBusProcessorOptions); 42 | processors.ProcessMessageAsync += WeekendSubscriptionMessagesAsync; 43 | processors.ProcessErrorAsync += ProcessErrorAsync; 44 | await processors.StartProcessingAsync(); 45 | _processors.Add(processors); 46 | 47 | var ruleProperties = await GetRuleProperties(SubscriptionNames.weekend.ToString()); 48 | await RemoveFilters(SubscriptionNames.weekend.ToString(), ruleProperties); 49 | await AddFilterToWeekend(SubscriptionNames.weekend.ToString()); 50 | } 51 | 52 | public async Task RegisterWeekdaySubscriptionAsync() 53 | { 54 | ServiceBusProcessorOptions serviceBusProcessorOptions = new ServiceBusProcessorOptions 55 | { AutoCompleteMessages = false }; 56 | 57 | var processors = _client.CreateProcessor(Constants.TopicName, SubscriptionNames.weekday.ToString(), serviceBusProcessorOptions); 58 | processors.ProcessMessageAsync += WeekdaySubscriptionMessagesAsync; 59 | processors.ProcessErrorAsync += ProcessErrorAsync; 60 | await processors.StartProcessingAsync(); 61 | _processors.Add(processors); 62 | var ruleProperties = await GetRuleProperties(SubscriptionNames.weekday.ToString()); 63 | await RemoveFilters(SubscriptionNames.weekday.ToString(), ruleProperties); 64 | await AddFilterToWeekday(SubscriptionNames.weekday.ToString()); 65 | } 66 | 67 | private async Task> GetRuleProperties(string subscriptionName) 68 | { 69 | try 70 | { 71 | var rules = _adminClient.GetRulesAsync(Constants.TopicName, subscriptionName); 72 | var ruleProperties = new List(); 73 | await foreach (var rule in rules) { ruleProperties.Add(rule); } 74 | return ruleProperties; 75 | } 76 | catch (Exception ex) 77 | { 78 | Console.WriteLine(ex.Message); 79 | } 80 | return null; 81 | } 82 | 83 | private async Task AddFilterToWeekend(string subscriptionName) 84 | { 85 | //var customKeyValueFilter = new CorrelationRuleFilter(); 86 | //customKeyValueFilter.ApplicationProperties["Day"] = "Saturday"; 87 | 88 | CreateRuleOptions createRuleOptions = new CreateRuleOptions 89 | { 90 | Name = "DaysFilter", 91 | Filter = new SqlRuleFilter("Day In ( 'Saturday', 'Sunday')") //customKeyValueFilter 92 | }; 93 | await _adminClient.CreateRuleAsync(Constants.TopicName, subscriptionName, createRuleOptions); 94 | } 95 | 96 | private async Task AddFilterToWeekday(string subscriptionName) 97 | { 98 | //var customKeyValueFilter = new CorrelationRuleFilter(); 99 | //customKeyValueFilter.ApplicationProperties["Day"] = "Saturday"; 100 | 101 | CreateRuleOptions createRuleOptions = new CreateRuleOptions 102 | { 103 | Name = "DaysFilter", 104 | Filter = new SqlRuleFilter("Day Not In ( 'Saturday', 'Sunday')") //customKeyValueFilter 105 | }; 106 | await _adminClient.CreateRuleAsync(Constants.TopicName, subscriptionName, createRuleOptions); 107 | } 108 | 109 | private async Task RemoveFilters(string subscriptionName, List ruleProperties) 110 | { 111 | try 112 | { 113 | foreach (var rule in ruleProperties) 114 | { 115 | await _adminClient.DeleteRuleAsync(Constants.TopicName, subscriptionName, rule.Name); // CreateRuleOptions.DefaultRuleName 116 | } 117 | } 118 | catch (Exception ex) 119 | { 120 | Console.WriteLine(ex.Message); 121 | } 122 | } 123 | 124 | private async Task WeekendSubscriptionMessagesAsync(ProcessMessageEventArgs arg) 125 | { 126 | var @event = arg.Message.Body.ToObjectFromJson(); 127 | var handlerTypes = _eventBusSubscriptionsManager.GetHandlersForEvent(@event.EventName, SubscriptionNames.weekend.ToString()); 128 | foreach (var handlerType in handlerTypes) 129 | { 130 | dynamic handlerInstance = _serviceProvider.GetService(handlerType); 131 | // http://techxposer.com/2018/01/03/missing-compiler-required-member-microsoft-csharp-runtimebinder-csharpargumentinfo-create-solved/ 132 | // https://social.msdn.microsoft.com/Forums/sharepoint/en-US/2b855369-a721-4010-9e33-72d699960994/how-to-fix-missing-compiler-member-error-microsoftcsharpruntimebindercsharpargumentinfocreate?forum=visualstudiogeneral 133 | await handlerInstance?.HandleAsync(@event); 134 | } 135 | await arg.CompleteMessageAsync(arg.Message); 136 | } 137 | 138 | private async Task WeekdaySubscriptionMessagesAsync(ProcessMessageEventArgs arg) 139 | { 140 | var @event = arg.Message.Body.ToObjectFromJson(); 141 | var handlerTypes = _eventBusSubscriptionsManager.GetHandlersForEvent(@event.EventName, SubscriptionNames.weekday.ToString()); 142 | foreach (var handlerType in handlerTypes) 143 | { 144 | dynamic handlerInstance = _serviceProvider.GetService(handlerType); 145 | // http://techxposer.com/2018/01/03/missing-compiler-required-member-microsoft-csharp-runtimebinder-csharpargumentinfo-create-solved/ 146 | // https://social.msdn.microsoft.com/Forums/sharepoint/en-US/2b855369-a721-4010-9e33-72d699960994/how-to-fix-missing-compiler-member-error-microsoftcsharpruntimebindercsharpargumentinfocreate?forum=visualstudiogeneral 147 | await handlerInstance?.HandleAsync(@event); 148 | } 149 | await arg.CompleteMessageAsync(arg.Message); 150 | } 151 | 152 | private Task ProcessErrorAsync(ProcessErrorEventArgs arg) 153 | { 154 | // log or do something 155 | return Task.CompletedTask; 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /Computer Vision POC/MsOCR_Demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Microsoft OCR Demo" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 43, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import os\n", 17 | "import sys\n", 18 | "import requests\n", 19 | "%matplotlib inline\n", 20 | "import matplotlib.pyplot as plt\n", 21 | "from matplotlib.patches import Rectangle\n", 22 | "from PIL import Image\n", 23 | "from io import BytesIO" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 44, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "if 'COMPUTER_VISION_SUBSCRIPTION_KEY' in os.environ:\n", 33 | " subscription_key = os.environ['COMPUTER_VISION_SUBSCRIPTION_KEY']\n", 34 | "else:\n", 35 | " print(\"\\nSet the COMPUTER_VISION_SUBSCRIPTION_KEY environment variable.\\n**Restart your shell or IDE for changes to take effect.**\")\n", 36 | " sys.exit()" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 45, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "if 'COMPUTER_VISION_ENDPOINT' in os.environ:\n", 46 | " endpoint = os.environ['COMPUTER_VISION_ENDPOINT']" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 46, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "ocr_url = endpoint + \"vision/v3.1/ocr\"" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "## OCR On image retrieved via URL" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 47, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "image_url = \"https://user-images.githubusercontent.com/2716202/102968699-5f950500-451a-11eb-84c4-cbc3bb3e886a.png\"" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 48, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "headers = {'Ocp-Apim-Subscription-Key': subscription_key}\n", 81 | "params = {'language': 'unk', 'detectOrientation': 'true'}\n", 82 | "data = {'url': image_url}\n", 83 | "response = requests.post(ocr_url, headers=headers, params=params, json=data)\n", 84 | "\n", 85 | "response.raise_for_status()\n", 86 | "\n", 87 | "analysis = response.json()" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 49, 93 | "metadata": {}, 94 | "outputs": [ 95 | { 96 | "name": "stdout", 97 | "output_type": "stream", 98 | "text": [ 99 | "{'language': 'en', 'textAngle': 0.0, 'orientation': 'Up', 'regions': [{'boundingBox': '56,114,494,326', 'lines': [{'boundingBox': '293,114,257,37', 'words': [{'boundingBox': '293,114,137,37', 'text': 'Infinite'}, {'boundingBox': '447,115,103,36', 'text': 'demo'}]}, {'boundingBox': '56,298,174,31', 'words': [{'boundingBox': '56,298,87,31', 'text': 'Python'}, {'boundingBox': '153,298,77,24', 'text': 'MsOcr'}]}, {'boundingBox': '56,383,281,26', 'words': [{'boundingBox': '56,383,281,26', 'text': 'python.msocr@domain.com'}]}, {'boundingBox': '56,420,111,20', 'words': [{'boundingBox': '56,420,65,20', 'text': 'Online'}, {'boundingBox': '129,420,38,20', 'text': 'POC'}]}]}, {'boundingBox': '636,337,156,108', 'lines': [{'boundingBox': '636,337,156,20', 'words': [{'boundingBox': '636,337,156,20', 'text': '+91-789123456'}]}, {'boundingBox': '654,384,134,21', 'words': [{'boundingBox': '654,384,74,20', 'text': 'Infinite'}, {'boundingBox': '735,384,53,21', 'text': 'demo'}]}, {'boundingBox': '708,420,83,25', 'words': [{'boundingBox': '708,420,83,25', 'text': 'youtube'}]}]}]}\n" 100 | ] 101 | } 102 | ], 103 | "source": [ 104 | "print(analysis)" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "## Formatted JSON\n", 112 | "```\n", 113 | "{\n", 114 | " \"language\": \"en\",\n", 115 | " \"textAngle\": 0.0,\n", 116 | " \"orientation\": \"Up\",\n", 117 | " \"regions\": [\n", 118 | " {\n", 119 | " \"boundingBox\": \"56,114,494,326\",\n", 120 | " \"lines\": [\n", 121 | " {\n", 122 | " \"boundingBox\": \"293,114,257,37\",\n", 123 | " \"words\": [\n", 124 | " { \"boundingBox\": \"293,114,137,37\", \"text\": \"Infinite\" },\n", 125 | " { \"boundingBox\": \"447,115,103,36\", \"text\": \"demo\" }\n", 126 | " ]\n", 127 | " },\n", 128 | " {\n", 129 | " \"boundingBox\": \"56,298,174,31\",\n", 130 | " \"words\": [\n", 131 | " { \"boundingBox\": \"56,298,87,31\", \"text\": \"Python\" },\n", 132 | " { \"boundingBox\": \"153,298,77,24\", \"text\": \"MsOcr\" }\n", 133 | " ]\n", 134 | " },\n", 135 | " {\n", 136 | " \"boundingBox\": \"56,383,281,26\",\n", 137 | " \"words\": [\n", 138 | " {\n", 139 | " \"boundingBox\": \"56,383,281,26\",\n", 140 | " \"text\": \"python.msocr@domain.com\"\n", 141 | " }\n", 142 | " ]\n", 143 | " },\n", 144 | " {\n", 145 | " \"boundingBox\": \"56,420,111,20\",\n", 146 | " \"words\": [\n", 147 | " { \"boundingBox\": \"56,420,65,20\", \"text\": \"Online\" },\n", 148 | " { \"boundingBox\": \"129,420,38,20\", \"text\": \"POC\" }\n", 149 | " ]\n", 150 | " }\n", 151 | " ]\n", 152 | " },\n", 153 | " {\n", 154 | " \"boundingBox\": \"636,337,156,108\",\n", 155 | " \"lines\": [\n", 156 | " {\n", 157 | " \"boundingBox\": \"636,337,156,20\",\n", 158 | " \"words\": [\n", 159 | " { \"boundingBox\": \"636,337,156,20\", \"text\": \"+91-789123456\" }\n", 160 | " ]\n", 161 | " },\n", 162 | " {\n", 163 | " \"boundingBox\": \"654,384,134,21\",\n", 164 | " \"words\": [\n", 165 | " { \"boundingBox\": \"654,384,74,20\", \"text\": \"Infinite\" },\n", 166 | " { \"boundingBox\": \"735,384,53,21\", \"text\": \"demo\" }\n", 167 | " ]\n", 168 | " },\n", 169 | " {\n", 170 | " \"boundingBox\": \"708,420,83,25\",\n", 171 | " \"words\": [{ \"boundingBox\": \"708,420,83,25\", \"text\": \"youtube\" }]\n", 172 | " }\n", 173 | " ]\n", 174 | " }\n", 175 | " ]\n", 176 | "}\n", 177 | "```" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 50, 183 | "metadata": {}, 184 | "outputs": [ 185 | { 186 | "data": { 187 | "text/plain": [ 188 | "[[{'boundingBox': '293,114,257,37',\n", 189 | " 'words': [{'boundingBox': '293,114,137,37', 'text': 'Infinite'},\n", 190 | " {'boundingBox': '447,115,103,36', 'text': 'demo'}]},\n", 191 | " {'boundingBox': '56,298,174,31',\n", 192 | " 'words': [{'boundingBox': '56,298,87,31', 'text': 'Python'},\n", 193 | " {'boundingBox': '153,298,77,24', 'text': 'MsOcr'}]},\n", 194 | " {'boundingBox': '56,383,281,26',\n", 195 | " 'words': [{'boundingBox': '56,383,281,26',\n", 196 | " 'text': 'python.msocr@domain.com'}]},\n", 197 | " {'boundingBox': '56,420,111,20',\n", 198 | " 'words': [{'boundingBox': '56,420,65,20', 'text': 'Online'},\n", 199 | " {'boundingBox': '129,420,38,20', 'text': 'POC'}]}],\n", 200 | " [{'boundingBox': '636,337,156,20',\n", 201 | " 'words': [{'boundingBox': '636,337,156,20', 'text': '+91-789123456'}]},\n", 202 | " {'boundingBox': '654,384,134,21',\n", 203 | " 'words': [{'boundingBox': '654,384,74,20', 'text': 'Infinite'},\n", 204 | " {'boundingBox': '735,384,53,21', 'text': 'demo'}]},\n", 205 | " {'boundingBox': '708,420,83,25',\n", 206 | " 'words': [{'boundingBox': '708,420,83,25', 'text': 'youtube'}]}]]" 207 | ] 208 | }, 209 | "execution_count": 50, 210 | "metadata": {}, 211 | "output_type": "execute_result" 212 | } 213 | ], 214 | "source": [ 215 | "# Extract the word bounding boxes and text.\n", 216 | "line_infos = [region[\"lines\"] for region in analysis[\"regions\"]]\n", 217 | "line_infos" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 51, 223 | "metadata": {}, 224 | "outputs": [ 225 | { 226 | "data": { 227 | "text/plain": [ 228 | "[{'boundingBox': '293,114,137,37', 'text': 'Infinite'},\n", 229 | " {'boundingBox': '447,115,103,36', 'text': 'demo'},\n", 230 | " {'boundingBox': '56,298,87,31', 'text': 'Python'},\n", 231 | " {'boundingBox': '153,298,77,24', 'text': 'MsOcr'},\n", 232 | " {'boundingBox': '56,383,281,26', 'text': 'python.msocr@domain.com'},\n", 233 | " {'boundingBox': '56,420,65,20', 'text': 'Online'},\n", 234 | " {'boundingBox': '129,420,38,20', 'text': 'POC'},\n", 235 | " {'boundingBox': '636,337,156,20', 'text': '+91-789123456'},\n", 236 | " {'boundingBox': '654,384,74,20', 'text': 'Infinite'},\n", 237 | " {'boundingBox': '735,384,53,21', 'text': 'demo'},\n", 238 | " {'boundingBox': '708,420,83,25', 'text': 'youtube'}]" 239 | ] 240 | }, 241 | "execution_count": 51, 242 | "metadata": {}, 243 | "output_type": "execute_result" 244 | } 245 | ], 246 | "source": [ 247 | "word_infos = []\n", 248 | "for line in line_infos:\n", 249 | " for word_metadata in line:\n", 250 | " for word_info in word_metadata[\"words\"]:\n", 251 | " word_infos.append(word_info)\n", 252 | "word_infos" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": 61, 258 | "metadata": {}, 259 | "outputs": [ 260 | { 261 | "data": { 262 | "image/png": "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\n", 263 | "text/plain": [ 264 | "
" 265 | ] 266 | }, 267 | "metadata": { 268 | "needs_background": "light" 269 | }, 270 | "output_type": "display_data" 271 | } 272 | ], 273 | "source": [ 274 | "# Display the image and overlay it with the extracted text.\n", 275 | "plt.figure(figsize=(5, 5))\n", 276 | "image = Image.open(BytesIO(requests.get(image_url).content))\n", 277 | "ax = plt.imshow(image, alpha=0.5)\n", 278 | "for word in word_infos:\n", 279 | " bbox = [int(num) for num in word[\"boundingBox\"].split(\",\")]\n", 280 | " text = word[\"text\"]\n", 281 | " origin = (bbox[0], bbox[1])\n", 282 | " patch = Rectangle(origin, bbox[2], bbox[3],\n", 283 | " fill=False, linewidth=2, color='y')\n", 284 | " ax.axes.add_patch(patch)\n", 285 | " plt.text(origin[0], origin[1], text, fontsize=10, va=\"top\")\n", 286 | "plt.axis(\"off\")\n", 287 | "plt.show()" 288 | ] 289 | }, 290 | { 291 | "cell_type": "markdown", 292 | "metadata": {}, 293 | "source": [ 294 | "## OCR On image stored on disk" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": 18, 300 | "metadata": {}, 301 | "outputs": [], 302 | "source": [ 303 | "image_path = './demoIdCard.png'" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": null, 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [ 312 | "# Read the image into a byte array\n", 313 | "image_data = open(image_path, \"rb\").read()\n", 314 | "# Set Content-Type to octet-stream\n", 315 | "headers = {'Ocp-Apim-Subscription-Key': subscription_key, 'Content-Type': 'application/octet-stream'}\n", 316 | "params = {'language': 'unk', 'detectOrientation': 'true'}\n", 317 | "# put the byte array into your post request\n", 318 | "response = requests.post(ocr_url, headers=headers, params=params, data = image_data)\n", 319 | "\n", 320 | "response.raise_for_status()\n", 321 | "\n", 322 | "analysis = response.json()" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": 26, 328 | "metadata": {}, 329 | "outputs": [ 330 | { 331 | "data": { 332 | "text/plain": [ 333 | "{'language': 'en',\n", 334 | " 'textAngle': 0.0,\n", 335 | " 'orientation': 'Up',\n", 336 | " 'regions': [{'boundingBox': '56,114,494,326',\n", 337 | " 'lines': [{'boundingBox': '293,114,257,37',\n", 338 | " 'words': [{'boundingBox': '293,114,137,37', 'text': 'Infinite'},\n", 339 | " {'boundingBox': '447,115,103,36', 'text': 'demo'}]},\n", 340 | " {'boundingBox': '56,298,174,31',\n", 341 | " 'words': [{'boundingBox': '56,298,87,31', 'text': 'Python'},\n", 342 | " {'boundingBox': '153,298,77,24', 'text': 'MsOcr'}]},\n", 343 | " {'boundingBox': '56,383,281,26',\n", 344 | " 'words': [{'boundingBox': '56,383,281,26',\n", 345 | " 'text': 'python.msocr@domain.com'}]},\n", 346 | " {'boundingBox': '56,420,111,20',\n", 347 | " 'words': [{'boundingBox': '56,420,65,20', 'text': 'Online'},\n", 348 | " {'boundingBox': '129,420,38,20', 'text': 'POC'}]}]},\n", 349 | " {'boundingBox': '636,337,156,108',\n", 350 | " 'lines': [{'boundingBox': '636,337,156,20',\n", 351 | " 'words': [{'boundingBox': '636,337,156,20', 'text': '+91-789123456'}]},\n", 352 | " {'boundingBox': '654,384,134,21',\n", 353 | " 'words': [{'boundingBox': '654,384,74,20', 'text': 'Infinite'},\n", 354 | " {'boundingBox': '735,384,53,21', 'text': 'demo'}]},\n", 355 | " {'boundingBox': '708,420,83,25',\n", 356 | " 'words': [{'boundingBox': '708,420,83,25', 'text': 'youtube'}]}]}]}" 357 | ] 358 | }, 359 | "execution_count": 26, 360 | "metadata": {}, 361 | "output_type": "execute_result" 362 | } 363 | ], 364 | "source": [ 365 | "analysis" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "metadata": {}, 371 | "source": [ 372 | "## Formatted JSON\n", 373 | "```\n", 374 | "{\n", 375 | " \"language\": \"en\",\n", 376 | " \"textAngle\": 0.0,\n", 377 | " \"orientation\": \"Up\",\n", 378 | " \"regions\": [\n", 379 | " {\n", 380 | " \"boundingBox\": \"56,114,494,326\",\n", 381 | " \"lines\": [\n", 382 | " {\n", 383 | " \"boundingBox\": \"293,114,257,37\",\n", 384 | " \"words\": [\n", 385 | " { \"boundingBox\": \"293,114,137,37\", \"text\": \"Infinite\" },\n", 386 | " { \"boundingBox\": \"447,115,103,36\", \"text\": \"demo\" }\n", 387 | " ]\n", 388 | " },\n", 389 | " {\n", 390 | " \"boundingBox\": \"56,298,174,31\",\n", 391 | " \"words\": [\n", 392 | " { \"boundingBox\": \"56,298,87,31\", \"text\": \"Python\" },\n", 393 | " { \"boundingBox\": \"153,298,77,24\", \"text\": \"MsOcr\" }\n", 394 | " ]\n", 395 | " },\n", 396 | " {\n", 397 | " \"boundingBox\": \"56,383,281,26\",\n", 398 | " \"words\": [\n", 399 | " {\n", 400 | " \"boundingBox\": \"56,383,281,26\",\n", 401 | " \"text\": \"python.msocr@domain.com\"\n", 402 | " }\n", 403 | " ]\n", 404 | " },\n", 405 | " {\n", 406 | " \"boundingBox\": \"56,420,111,20\",\n", 407 | " \"words\": [\n", 408 | " { \"boundingBox\": \"56,420,65,20\", \"text\": \"Online\" },\n", 409 | " { \"boundingBox\": \"129,420,38,20\", \"text\": \"POC\" }\n", 410 | " ]\n", 411 | " }\n", 412 | " ]\n", 413 | " },\n", 414 | " {\n", 415 | " \"boundingBox\": \"636,337,156,108\",\n", 416 | " \"lines\": [\n", 417 | " {\n", 418 | " \"boundingBox\": \"636,337,156,20\",\n", 419 | " \"words\": [\n", 420 | " { \"boundingBox\": \"636,337,156,20\", \"text\": \"+91-789123456\" }\n", 421 | " ]\n", 422 | " },\n", 423 | " {\n", 424 | " \"boundingBox\": \"654,384,134,21\",\n", 425 | " \"words\": [\n", 426 | " { \"boundingBox\": \"654,384,74,20\", \"text\": \"Infinite\" },\n", 427 | " { \"boundingBox\": \"735,384,53,21\", \"text\": \"demo\" }\n", 428 | " ]\n", 429 | " },\n", 430 | " {\n", 431 | " \"boundingBox\": \"708,420,83,25\",\n", 432 | " \"words\": [{ \"boundingBox\": \"708,420,83,25\", \"text\": \"youtube\" }]\n", 433 | " }\n", 434 | " ]\n", 435 | " }\n", 436 | " ]\n", 437 | "}\n", 438 | "```" 439 | ] 440 | }, 441 | { 442 | "cell_type": "code", 443 | "execution_count": 23, 444 | "metadata": {}, 445 | "outputs": [ 446 | { 447 | "data": { 448 | "text/plain": [ 449 | "[[{'boundingBox': '293,114,257,37',\n", 450 | " 'words': [{'boundingBox': '293,114,137,37', 'text': 'Infinite'},\n", 451 | " {'boundingBox': '447,115,103,36', 'text': 'demo'}]},\n", 452 | " {'boundingBox': '56,298,174,31',\n", 453 | " 'words': [{'boundingBox': '56,298,87,31', 'text': 'Python'},\n", 454 | " {'boundingBox': '153,298,77,24', 'text': 'MsOcr'}]},\n", 455 | " {'boundingBox': '56,383,281,26',\n", 456 | " 'words': [{'boundingBox': '56,383,281,26',\n", 457 | " 'text': 'python.msocr@domain.com'}]},\n", 458 | " {'boundingBox': '56,420,111,20',\n", 459 | " 'words': [{'boundingBox': '56,420,65,20', 'text': 'Online'},\n", 460 | " {'boundingBox': '129,420,38,20', 'text': 'POC'}]}],\n", 461 | " [{'boundingBox': '636,337,156,20',\n", 462 | " 'words': [{'boundingBox': '636,337,156,20', 'text': '+91-789123456'}]},\n", 463 | " {'boundingBox': '654,384,134,21',\n", 464 | " 'words': [{'boundingBox': '654,384,74,20', 'text': 'Infinite'},\n", 465 | " {'boundingBox': '735,384,53,21', 'text': 'demo'}]},\n", 466 | " {'boundingBox': '708,420,83,25',\n", 467 | " 'words': [{'boundingBox': '708,420,83,25', 'text': 'youtube'}]}]]" 468 | ] 469 | }, 470 | "execution_count": 23, 471 | "metadata": {}, 472 | "output_type": "execute_result" 473 | } 474 | ], 475 | "source": [ 476 | "# Extract the word bounding boxes and text.\n", 477 | "line_infos = [region[\"lines\"] for region in analysis[\"regions\"]]\n", 478 | "line_infos" 479 | ] 480 | }, 481 | { 482 | "cell_type": "code", 483 | "execution_count": 24, 484 | "metadata": {}, 485 | "outputs": [ 486 | { 487 | "data": { 488 | "text/plain": [ 489 | "[{'boundingBox': '293,114,137,37', 'text': 'Infinite'},\n", 490 | " {'boundingBox': '447,115,103,36', 'text': 'demo'},\n", 491 | " {'boundingBox': '56,298,87,31', 'text': 'Python'},\n", 492 | " {'boundingBox': '153,298,77,24', 'text': 'MsOcr'},\n", 493 | " {'boundingBox': '56,383,281,26', 'text': 'python.msocr@domain.com'},\n", 494 | " {'boundingBox': '56,420,65,20', 'text': 'Online'},\n", 495 | " {'boundingBox': '129,420,38,20', 'text': 'POC'},\n", 496 | " {'boundingBox': '636,337,156,20', 'text': '+91-789123456'},\n", 497 | " {'boundingBox': '654,384,74,20', 'text': 'Infinite'},\n", 498 | " {'boundingBox': '735,384,53,21', 'text': 'demo'},\n", 499 | " {'boundingBox': '708,420,83,25', 'text': 'youtube'}]" 500 | ] 501 | }, 502 | "execution_count": 24, 503 | "metadata": {}, 504 | "output_type": "execute_result" 505 | } 506 | ], 507 | "source": [ 508 | "word_infos = []\n", 509 | "for line in line_infos:\n", 510 | " for word_metadata in line:\n", 511 | " for word_info in word_metadata[\"words\"]:\n", 512 | " word_infos.append(word_info)\n", 513 | "word_infos" 514 | ] 515 | }, 516 | { 517 | "cell_type": "code", 518 | "execution_count": 62, 519 | "metadata": {}, 520 | "outputs": [ 521 | { 522 | "data": { 523 | "image/png": "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\n", 524 | "text/plain": [ 525 | "
" 526 | ] 527 | }, 528 | "metadata": { 529 | "needs_background": "light" 530 | }, 531 | "output_type": "display_data" 532 | } 533 | ], 534 | "source": [ 535 | "# Display the image and overlay it with the extracted text.\n", 536 | "plt.figure(figsize=(5, 5))\n", 537 | "image = Image.open(BytesIO(requests.get(image_url).content))\n", 538 | "ax = plt.imshow(image, alpha=0.5)\n", 539 | "for word in word_infos:\n", 540 | " bbox = [int(num) for num in word[\"boundingBox\"].split(\",\")]\n", 541 | " text = word[\"text\"]\n", 542 | " origin = (bbox[0], bbox[1])\n", 543 | " patch = Rectangle(origin, bbox[2], bbox[3],\n", 544 | " fill=False, linewidth=2, color='y')\n", 545 | " ax.axes.add_patch(patch)\n", 546 | " plt.text(origin[0], origin[1], text, fontsize=20, weight=\"bold\", va=\"top\")\n", 547 | "plt.axis(\"off\")\n", 548 | "plt.show()" 549 | ] 550 | } 551 | ], 552 | "metadata": { 553 | "kernelspec": { 554 | "display_name": "Python 3", 555 | "language": "python", 556 | "name": "python3" 557 | }, 558 | "language_info": { 559 | "codemirror_mode": { 560 | "name": "ipython", 561 | "version": 3 562 | }, 563 | "file_extension": ".py", 564 | "mimetype": "text/x-python", 565 | "name": "python", 566 | "nbconvert_exporter": "python", 567 | "pygments_lexer": "ipython3", 568 | "version": "3.8.5" 569 | } 570 | }, 571 | "nbformat": 4, 572 | "nbformat_minor": 4 573 | } 574 | --------------------------------------------------------------------------------