Skip to content

Commit

Permalink
.NET: Code Example for AWS Message Processing Framework for .NET. (#6474
Browse files Browse the repository at this point in the history
)

* Capturing code examples for the AWS Message Processing Framework for .NET.

---------

Co-authored-by: Rachel Hagerman <[email protected]>
  • Loading branch information
Paul-B-AWS and rlhagerm authored May 22, 2024
1 parent 04518a6 commit 0b22105
Show file tree
Hide file tree
Showing 15 changed files with 486 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "file://zonbook/docbookx.dtd"[
<!ENTITY % phrases-shared SYSTEM "file://AWSShared/common/phrases-shared.ent">
%phrases-shared;
]>
<block>
<para>Provides a tutorial for the &AWS; Message Processing Framework for .NET. The tutorial creates a web application that
allows the user to publish an &SQS; message and a command-line application that receives the message.</para>
<para>For complete source code and instructions on how to set up and run, see the <ulink
url="&url-net-dev;msg-proc-fw-get-started.html">full tutorial</ulink> in the &guide-net-dev; and the
example on <ulink
url="https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/cross-service/MessageProcessingFramework"
>GitHub</ulink>.</para>
</block>
14 changes: 14 additions & 0 deletions .doc_gen/metadata/cross_metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# zexi 0.4.0
cross_MessageProcessingFrameworkTutorial:
title: Use the &AWS; Message Processing Framework for .NET to publish and receive &SQS; messages
title_abbrev: Use the &AWS; Message Processing Framework for .NET with &SQS;
synopsis: create applications that publish and receive &SQS; messages using the &AWS; Message Processing Framework for .NET.
category: Cross-service examples
languages:
.NET:
versions:
- sdk_version: 3
github: dotnetv3/cross-service/MessageProcessingFramework
block_content: cross_MessageProcessingFramework_Net_block.xml
service_main: sqs
services:
sqs:
cross_FSA:
title: Create an application that analyzes customer feedback and synthesizes audio
title_abbrev: Create an application to analyze customer feedback
Expand Down
6 changes: 6 additions & 0 deletions dotnetv3/SQS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ functions within the same service.

- [Publish messages to queues](../cross-service/TopicsAndQueues/Scenarios/TopicsAndQueuesScenario/TopicsAndQueues.cs)

### Cross-service examples

Sample applications that work across multiple AWS services.

- [Use the AWS Message Processing Framework for .NET with Amazon SQS](../cross-service/MessageProcessingFramework)


<!--custom.examples.start-->
<!--custom.examples.end-->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWS.Messaging" Version="0.9.0" />
<PackageReference Include="AWSSDK.SSO" Version="3.7.300.74" />
<PackageReference Include="AWSSDK.SSOOIDC" Version="3.7.301.69" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

// snippet-start:[SQS.dotnetv3.MPFTutorial.Handler]

using AWS.Messaging;
using Handler;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = Host.CreateDefaultBuilder(args);

builder.ConfigureServices(services =>
{
// Register the AWS Message Processing Framework for .NET.
services.AddAWSMessageBus(builder =>
{
// Check for input SQS URL.
// The SQS URL should be passed as a command line argument or set in the Debug launch profile.
if ((args.Length == 1) && (args[0].Contains("https://sqs.")))
{
// Register you'll poll the following queue.
builder.AddSQSPoller(args[0]);

// And that messages of type "greetingMessage" should be:
// 1. Deserialized as GreetingMessage objects.
// 2. Which are then passed to GreetingMessageHandler.
builder.AddMessageHandler<GreetingMessageHandler, GreetingMessage>("greetingMessage");

}
// You can add additional message handlers here, using different message types.
});
});

var host = builder.Build();
await host.RunAsync();

namespace Handler
{
/// <summary>
/// This class represents the message contents.
/// </summary>
public class GreetingMessage
{
public string? SenderName { get; set; }
public string? Greeting { get; set; }
}

/// <summary>
/// This handler is invoked each time you receive the message.
/// </summary>
public class GreetingMessageHandler : IMessageHandler<GreetingMessage>
{
public Task<MessageProcessStatus> HandleAsync(
MessageEnvelope<GreetingMessage> messageEnvelope,
CancellationToken token = default)
{
Console.WriteLine(
$"Received message {messageEnvelope.Message.Greeting} from {messageEnvelope.Message.SenderName}");
return Task.FromResult(MessageProcessStatus.Success());
}
}
}
// snippet-end:[SQS.dotnetv3.MPFTutorial.Handler]
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Publisher", "Publisher\Publisher.csproj", "{3BC3587D-01BA-4321-A3C5-EF0253B9FB5D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Handler", "Handler\Handler.csproj", "{9D2F2EFD-F308-41A2-8D1C-EEAE6738684F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MessageProcessingFrameworkTests", "Tests\MessageProcessingFrameworkTests.csproj", "{64706E28-3BC4-4DD5-9124-336FED9F14CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3BC3587D-01BA-4321-A3C5-EF0253B9FB5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BC3587D-01BA-4321-A3C5-EF0253B9FB5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BC3587D-01BA-4321-A3C5-EF0253B9FB5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BC3587D-01BA-4321-A3C5-EF0253B9FB5D}.Release|Any CPU.Build.0 = Release|Any CPU
{9D2F2EFD-F308-41A2-8D1C-EEAE6738684F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D2F2EFD-F308-41A2-8D1C-EEAE6738684F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D2F2EFD-F308-41A2-8D1C-EEAE6738684F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D2F2EFD-F308-41A2-8D1C-EEAE6738684F}.Release|Any CPU.Build.0 = Release|Any CPU
{64706E28-3BC4-4DD5-9124-336FED9F14CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64706E28-3BC4-4DD5-9124-336FED9F14CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64706E28-3BC4-4DD5-9124-336FED9F14CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64706E28-3BC4-4DD5-9124-336FED9F14CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

// snippet-start:[SQS.dotnetv3.MPFTutorial.Publisher]
using AWS.Messaging;
using Microsoft.AspNetCore.Mvc;
using Publisher;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();


// Configure the AWS Message Processing Framework for .NET.
builder.Services.AddAWSMessageBus(builder =>
{
// Check for input SQS URL.
// The SQS URL should be passed as a command line argument or set in the Debug launch profile.
if ((args.Length == 1) && (args[0].Contains("https://sqs.")))
{
// Register that you'll publish messages of type GreetingMessage:
// 1. To a specified queue.
// 2. Using the message identifier "greetingMessage", which will be used
// by handlers to route the message to the appropriate handler.
builder.AddSQSPublisher<GreetingMessage>(args[0], "greetingMessage");
}
// You can map additional message types to queues or topics here as well.
});
var app = builder.Build();


// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// Create an API Endpoint that receives GreetingMessage objects
// from the caller and then sends them as an SQS message.
app.MapPost("/greeting", async ([FromServices] IMessagePublisher publisher, Publisher.GreetingMessage message) =>
{
return await PostGreeting(message, publisher);
})
.WithName("SendGreeting")
.WithOpenApi();

app.Run();

public partial class Program
{
/// <summary>
/// Endpoint for posting a greeting message.
/// </summary>
/// <param name="greetingMessage">The greeting message.</param>
/// <param name="messagePublisher">The message publisher.</param>
/// <returns>Async task result.</returns>
public static async Task<IResult> PostGreeting(GreetingMessage greetingMessage,
IMessagePublisher messagePublisher)
{
if (greetingMessage.SenderName == null || greetingMessage.Greeting == null)
{
return Results.BadRequest();
}

// Publish the message to the queue configured above.
await messagePublisher.PublishAsync(greetingMessage);

return Results.Ok();
}
}

namespace Publisher
{
/// <summary>
/// This class represents the message contents.
/// </summary>
public class GreetingMessage
{
public string? SenderName { get; set; }
public string? Greeting { get; set; }
}
}
// snippet-end:[SQS.dotnetv3.MPFTutorial.Publisher]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:42714",
"sslPort": 44395
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5239",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7043;http://localhost:5239",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWS.Messaging" Version="0.9.0" />
<PackageReference Include="AWSSDK.SSO" Version="3.7.300.74" />
<PackageReference Include="AWSSDK.SSOOIDC" Version="3.7.301.69" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions dotnetv3/cross-service/MessageProcessingFramework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Get started with the AWS Message Processing Framework for .NET

## Overview

This example shows you how to get started with the AWS Message Processing Framework for .NET. The tutorial creates a web application that allows the user to publish an Amazon SQS message and a command-line application that receives the message. For the complete tutorial along with prerequisites, setup, and run instructions, see the [AWS SDK for .NET Developer Guide](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/msg-proc-fw-get-started.html).

## Prerequisites

- Follow the main [README](../../README.md#Prerequisites) in the `dotnetv3` folder
- To set up your development environment see [Get started with the AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-setup.html).

### Important

- Running this code might result in charges to your AWS account.
Be sure to delete all the resources you create while going through this tutorial so that you won't be charged.
- Running the tests might result in charges to your AWS account.
- This code has not been tested in all AWS Regions. Some AWS services are available only in specific Regions. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
- We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).

### .NET Implementation Details
- If you're using AWS IAM Identity Center for authentication, be sure to also add the `AWSSDK.SSO` and `AWSSDK.SSOOIDC` NuGet packages to the projects.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using AWS.Messaging;
using Handler;

namespace MessageProcessingFrameworkTests;

public class HandlerTests
{
/// <summary>
/// Handle a message. Should return success status.
/// </summary>
/// <returns>Async task.</returns>
[Fact]
public async Task TestHandleMessage()
{
// Arrange.
var handler = new GreetingMessageHandler();

var message = new Handler.GreetingMessage()
{
SenderName = "Sender",
Greeting = "Hello"
};

var envelope = new MessageEnvelope<Handler.GreetingMessage>()
{
Message = message
};

// Act.
var response = await handler.HandleAsync(envelope);

// Assert.
Assert.True(response.IsSuccess);
}
}
Loading

0 comments on commit 0b22105

Please sign in to comment.