├── 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 |
--------------------------------------------------------------------------------