Skip to content

Commit 2cc50f5

Browse files
Merge branch 'documentation'
2 parents 5a28430 + 093ab4a commit 2cc50f5

File tree

9 files changed

+315
-2
lines changed

9 files changed

+315
-2
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,3 +349,5 @@ MigrationBackup/
349349
# Ionide (cross platform F# VS Code tools) working folder
350350
.ionide/
351351
.idea/
352+
sample/SampleApi/appsettings.Development.json
353+
Atc.Azure.Messaging.lutconfig

Atc.Azure.Messaging.sln

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ VisualStudioVersion = 17.0.31903.59
55
MinimumVisualStudioVersion = 15.0.26124.0
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Azure.Messaging", "src\Atc.Azure.Messaging\Atc.Azure.Messaging.csproj", "{2F7702F2-A407-41FB-8C88-7C066237BC75}"
77
EndProject
8-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atc.Azure.Messaging.Tests", "test\Atc.Azure.Messaging.Tests\Atc.Azure.Messaging.Tests.csproj", "{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}"
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Azure.Messaging.Tests", "test\Atc.Azure.Messaging.Tests\Atc.Azure.Messaging.Tests.csproj", "{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{80664A26-621B-4C22-B341-44EB3CA66724}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "sample\SampleApi\SampleApi.csproj", "{FEFE9828-0DA9-4C88-8D45-416D889012B6}"
913
EndProject
1014
Global
1115
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,10 +25,17 @@ Global
2125
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
2226
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
2327
{0C49EE44-DAE3-4A7C-9D2D-D1190CAC85F0}.Release|Any CPU.Build.0 = Release|Any CPU
28+
{FEFE9828-0DA9-4C88-8D45-416D889012B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29+
{FEFE9828-0DA9-4C88-8D45-416D889012B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
30+
{FEFE9828-0DA9-4C88-8D45-416D889012B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
31+
{FEFE9828-0DA9-4C88-8D45-416D889012B6}.Release|Any CPU.Build.0 = Release|Any CPU
2432
EndGlobalSection
2533
GlobalSection(SolutionProperties) = preSolution
2634
HideSolutionNode = FALSE
2735
EndGlobalSection
36+
GlobalSection(NestedProjects) = preSolution
37+
{FEFE9828-0DA9-4C88-8D45-416D889012B6} = {80664A26-621B-4C22-B341-44EB3CA66724}
38+
EndGlobalSection
2839
GlobalSection(ExtensibilityGlobals) = postSolution
2940
SolutionGuid = {1EC093F7-1E03-4088-BA72-0DEB39AFEE82}
3041
EndGlobalSection

README.md

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,155 @@
33

44
# ATC Azure Messaging
55

6-
A component library for publishing messages on Azure Event Hubs and Service Bus.
6+
A .NET component library for publishing messages on Azure Event Hubs and Service Bus. This targets .NET Standard 2.1 and depends on [ATC Azure Options](https://github.com/atc-net/atc-azure-options).
7+
8+
# Getting Started
9+
10+
The first thing you need to do to make sure that your configuration is setup correctly. For the sake of simplicity, let's use the `appsettings.json` file created with every .NET project
11+
12+
The following is an example of how your would configure your EventHub or ServiceBus for [ATC Azure Options](https://github.com/atc-net/atc-azure-options)
13+
14+
```json
15+
{
16+
"EventHubOptions": {
17+
"ConnectionString": "Endpoint=sb://[your eventhub namespace].servicebus.windows.net/;SharedAccessKeyName=[eventhub name];SharedAccessKey=[sas key]"
18+
},
19+
"ServiceBusOptions": {
20+
"ConnectionString": "Endpoint=sb://[your servicebus namespace].servicebus.windows.net/;SharedAccessKeyName=[topic|queue name];SharedAccessKey=[sas key]"
21+
}
22+
}
23+
```
24+
25+
When binding to KeyVault this should of course be `EventHubOptions--ConnectionString` for EventHub or `ServiceBusOptions--ConnectionString` for ServiceBus
26+
27+
The next step is to register the dependencies required to use this component library. For this you can use the `IServiceCollection` extension method `ConfigureMessagingServices(IConfiguration)`. This piggy backs over the `Microsoft.Extensions.DependencyInjection` namespace so that you don't need to include anything extra using statements
28+
29+
Here's an example of how to do this using a Minimal API setup
30+
31+
```csharp
32+
var builder = WebApplication.CreateBuilder(args);
33+
builder.Services.AddEndpointsApiExplorer();
34+
builder.Services.AddSwaggerGen();
35+
36+
// Register Atc.Azure.Messaging dependencies
37+
builder.Services.ConfigureMessagingServices(builder.Configuration);
38+
```
39+
40+
## Publishing to EventHub
41+
42+
To publish events to an EventHub you need an instance of `IEventHubPublisher`, this can be constructed via the `IEventHubPublisherFactory` which exposes the `Create(string eventHubName)` method
43+
44+
```csharp
45+
internal class FooPublisher
46+
{
47+
private readonly IEventHubPublisher publisher;
48+
49+
public FooPublisher(IEventHubPublisherFactory factory)
50+
{
51+
publisher = factory.Create([existing eventhub name]);
52+
}
53+
54+
public Task Publish(object message)
55+
=> publisher
56+
.PublishAsync(
57+
bar,
58+
new Dictionary<string, string>
59+
{
60+
{"messageType", nameof(message)}
61+
}
62+
)
63+
}
64+
```
65+
66+
## Publishing to ServiceBus
67+
68+
To publish events to a ServiceBus topic or queue you need an instance of `IServiceBusPublisher`
69+
70+
```csharp
71+
internal class BarPublisher
72+
{
73+
private readonly IServiceBusPublisher publisher;
74+
75+
public BarPublisher(IServiceBusPublisher publisher)
76+
{
77+
this.publisher = publisher;
78+
}
79+
80+
public Task Publish(object message)
81+
=> publisher
82+
.PublishAsync(
83+
"[existing servicebus topic]",
84+
"[session id or nothing]",
85+
JsonSerializer.Serialize(message));
86+
}
87+
```
88+
89+
Here's a full example of how to use the publishers above using a Minimal API setup (SwaggerUI enabled) with a single endpoint called `POST /data` that accepts a simple request body `{ "a": "string", "b": "string", "c": "string" }` which publishes the request to an EventHub and a ServiceBus topic
90+
91+
```csharp
92+
var builder = WebApplication.CreateBuilder(args);
93+
builder.Services.AddEndpointsApiExplorer();
94+
builder.Services.AddSwaggerGen();
95+
builder.Services.AddSingleton<SendDataHandler>();
96+
97+
// Register Atc.Azure.Messaging dependencies
98+
builder.Services.ConfigureMessagingServices(builder.Configuration);
99+
100+
var app = builder.Build();
101+
app.UseHttpsRedirection();
102+
if (app.Environment.IsDevelopment())
103+
{
104+
app.UseSwagger();
105+
app.UseSwaggerUI();
106+
}
107+
108+
app.MapPost(
109+
"/data",
110+
(Request request, SendDataHandler handler) => handler.Post(request));
111+
112+
app.Run();
113+
114+
internal class SendDataHandler
115+
{
116+
private readonly IEventHubPublisher eventHubPublisher;
117+
private readonly IServiceBusPublisher serviceBusPublisher;
118+
119+
public SendDataHandler(
120+
IEventHubPublisherFactory eventHubFactory,
121+
IServiceBusPublisher serviceBusPublisher)
122+
{
123+
eventHubPublisher = eventHubFactory.Create("[existing eventhub]");
124+
this.serviceBusPublisher = serviceBusPublisher;
125+
}
126+
127+
public async Task<Response> Post(Request request)
128+
{
129+
await eventHubPublisher
130+
.PublishAsync(
131+
request,
132+
new Dictionary<string, string>(StringComparer.Ordinal)
133+
{
134+
{ "MessageType", "example" },
135+
});
136+
137+
await serviceBusPublisher
138+
.PublishAsync(
139+
"[existing topic|queue",
140+
"[session id or nothing]",
141+
System.Text.Json.JsonSerializer.Serialize(request));
142+
143+
return new Response(
144+
Guid.NewGuid().ToString("N"),
145+
request.A,
146+
request.B,
147+
request.C);
148+
}
149+
}
150+
151+
internal record Request(string A, string B, string C);
152+
153+
internal record Response(string Id, string A, string B, string C);
154+
```
7155

8156

9157
# The workflow setup for this repository

sample/SampleApi/Program.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System.Text.Json;
2+
using Atc.Azure.Messaging.EventHub;
3+
using Atc.Azure.Messaging.ServiceBus;
4+
5+
var builder = WebApplication.CreateBuilder(args);
6+
builder.Services.AddEndpointsApiExplorer();
7+
builder.Services.AddSwaggerGen();
8+
builder.Services.AddSingleton<SendDataHandler>();
9+
10+
// Register Atc.Azure.Messaging dependencies
11+
builder.Services.ConfigureMessagingServices(builder.Configuration);
12+
13+
var app = builder.Build();
14+
app.UseHttpsRedirection();
15+
if (app.Environment.IsDevelopment())
16+
{
17+
app.UseSwagger();
18+
app.UseSwaggerUI();
19+
}
20+
21+
app.MapPost(
22+
"/data",
23+
(Request request, SendDataHandler handler) => handler.Post(request));
24+
25+
app.Run();
26+
27+
#pragma warning disable MA0048 // File name must match type name
28+
#pragma warning disable SA1649 // File name should match first type name
29+
#pragma warning disable MA0047 // Declare types in namespaces
30+
#pragma warning disable S3903 // Types should be defined in named namespaces
31+
32+
internal class SendDataHandler
33+
{
34+
private readonly IEventHubPublisher eventHubPublisher;
35+
private readonly IServiceBusPublisher serviceBusPublisher;
36+
37+
public SendDataHandler(
38+
IEventHubPublisherFactory eventHubFactory,
39+
IServiceBusPublisher serviceBusPublisher)
40+
{
41+
eventHubPublisher = eventHubFactory.Create("[existing eventhub]");
42+
this.serviceBusPublisher = serviceBusPublisher;
43+
}
44+
45+
public async Task<Response> Post(Request request)
46+
{
47+
await eventHubPublisher
48+
.PublishAsync(
49+
request,
50+
new Dictionary<string, string>(StringComparer.Ordinal)
51+
{
52+
{ "MessageType", "example" },
53+
});
54+
55+
await serviceBusPublisher
56+
.PublishAsync(
57+
"[existing topic|queue",
58+
"[session id or nothing]",
59+
JsonSerializer.Serialize(request));
60+
61+
return new Response(
62+
Guid.NewGuid().ToString("N"),
63+
request.A,
64+
request.B,
65+
request.C);
66+
}
67+
}
68+
69+
internal record Request(string A, string B, string C);
70+
71+
internal record Response(string Id, string A, string B, string C);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"iisSettings": {
4+
"windowsAuthentication": false,
5+
"anonymousAuthentication": true,
6+
"iisExpress": {
7+
"applicationUrl": "http://localhost:20787",
8+
"sslPort": 44330
9+
}
10+
},
11+
"profiles": {
12+
"SampleApi": {
13+
"commandName": "Project",
14+
"dotnetRunMessages": true,
15+
"launchBrowser": true,
16+
"launchUrl": "swagger",
17+
"applicationUrl": "https://localhost:7091;http://localhost:5091",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
},
22+
"IIS Express": {
23+
"commandName": "IISExpress",
24+
"launchBrowser": true,
25+
"launchUrl": "swagger",
26+
"environmentVariables": {
27+
"ASPNETCORE_ENVIRONMENT": "Development"
28+
}
29+
}
30+
}
31+
}

sample/SampleApi/SampleApi.csproj

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<ProjectReference Include="..\..\src\Atc.Azure.Messaging\Atc.Azure.Messaging.csproj" />
15+
</ItemGroup>
16+
17+
</Project>

sample/SampleApi/appsettings.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*",
9+
"EventHubOptions": {
10+
"ConnectionString": "Endpoint=sb://[your eventhub namespace].servicebus.windows.net/;SharedAccessKeyName=[eventhub name];SharedAccessKey=[sas key]"
11+
}
12+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*",
9+
"NamingOptions": {
10+
"CompanyAbbreviation": "cl",
11+
"SystemAbbreviation": "cpms",
12+
"ServiceAbbreviation": "ocpi"
13+
}
14+
}

src/Atc.Azure.Messaging/Atc.Azure.Messaging.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,15 @@
55
<PackageId>Atc.Azure.Messaging</PackageId>
66
<PackageTags>azure;eventhubs;servicebus</PackageTags>
77
<Description>A component library for publishing messages on Azure Event Hubs and Service Bus.</Description>
8+
<PackageProjectUrl>https://github.com/atc-net/atc-azure-messaging/blob/main/README.md</PackageProjectUrl>
9+
<RepositoryUrl>https://github.com/atc-net/atc-azure-messaging</RepositoryUrl>
10+
<PackageReadmeFile>README.md</PackageReadmeFile>
811
</PropertyGroup>
912

13+
<ItemGroup>
14+
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
15+
</ItemGroup>
16+
1017
<ItemGroup>
1118
<PackageReference Include="Atc.Azure.Options" Version="3.0.14" />
1219
<PackageReference Include="Azure.Messaging.EventHubs" Version="5.7.0" />

0 commit comments

Comments
 (0)