Upgraded to ASP.NET Core 6 Minimal API

Signed-off-by: Arash Rohani <arash.rohani@gmail.com>
This commit is contained in:
Arash Rohani 2022-05-07 18:17:59 -07:00 committed by Arash Rohani
parent b0a70d9e61
commit 5c6fc9b029
16 changed files with 131 additions and 251 deletions

View File

@ -1,44 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Dapr;
using csharp_subscriber.Models;
namespace csharp_subscriber.Controllers
{
[ApiController]
public class MessageController : ControllerBase
{
private readonly ILogger<MessageController> _logger;
public MessageController(ILogger<MessageController> logger)
{
_logger = logger;
}
[Topic("pubsub", "A")]
[HttpPost("A")]
public ActionResult TopicA(MessageEvent item)
{
_logger.LogInformation($"{item.MessageType}: {item.Message}");
return Ok();
}
[Topic("pubsub", "B")]
[HttpPost("B")]
public ActionResult TopicB(MessageEvent item)
{
_logger.LogInformation($"{item.MessageType}: {item.Message}");
return Ok();
}
[Topic("pubsub", "C")]
[HttpPost("C")]
public ActionResult TopicC(Dictionary<string, string> item)
{
_logger.LogInformation($"{item["messageType"]}: {item["message"]}");
return Ok();
}
}
}

View File

@ -1,26 +0,0 @@
FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal AS base
WORKDIR /app
EXPOSE 5009
ENV ASPNETCORE_URLS=http://+:5009
# Creates a non-root user with an explicit UID and adds permission to access the /app folder
# For more info, please refer to https://aka.ms/vscode-docker-dotnet-configure-containers
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser
FROM mcr.microsoft.com/dotnet/sdk:5.0-focal AS build
WORKDIR /src
COPY ["csharp-subscriber.csproj", "./"]
RUN dotnet restore "csharp-subscriber.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "csharp-subscriber.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "csharp-subscriber.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "csharp-subscriber.dll"]

View File

@ -1,12 +0,0 @@
using System;
namespace csharp_subscriber.Models
{
public class MessageEvent
{
public string MessageType { get; set; }
public string Message { get; set; }
}
}

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace csharp_subscriber
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

View File

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
namespace csharp_subscriber
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddDapr();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "csharp_subscriber", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "csharp_subscriber v1"));
}
app.UseRouting();
app.UseCloudEvents();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapSubscribeHandler();
endpoints.MapControllers();
});
}
}
}

View File

@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>csharp_subscriber</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapr.AspNetCore" Version="1.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
</ItemGroup>
</Project>

View File

@ -25,7 +25,7 @@ Dapr allows you to deploy the same microservices from your local machines to the
### Prerequisites to run locally
- [Dapr CLI with Dapr initialized](https://docs.dapr.io/getting-started/install-dapr-cli/)
- [Node.js version 8 or greater](https://nodejs.org/en/) and/or [Python 3.4 or greater](https://www.python.org/) and/or [Asp.Net Core 5](https://dotnet.microsoft.com/download/dotnet/5.0): You can run this quickstart with one or both or all microservices
- [Node.js version 8 or greater](https://nodejs.org/en/) and/or [Python 3.4 or greater](https://www.python.org/) and/or [Asp.Net Core 6](https://dotnet.microsoft.com/download/dotnet/6.0): You can run this quickstart with one or both or all microservices
### Prerequisites to Run in Kubernetes
@ -290,6 +290,7 @@ curl -s http://localhost:8080/publish -H Content-Type:application/json --data @m
expected_stdout_lines:
- 'app stopped successfully: node-subscriber'
- 'app stopped successfully: python-subscriber'
- 'app stopped successfully: csharp-subscriber'
- 'app stopped successfully: react-form'
expected_stderr_lines:
output_match_mode: substring
@ -304,6 +305,10 @@ dapr stop --app-id node-subscriber
dapr stop --app-id python-subscriber
```
```bash
dapr stop --app-id csharp-subscriber
```
```bash
dapr stop --app-id react-form
```
@ -333,7 +338,7 @@ Dapr uses pluggable message buses to enable pub-sub, in this case Redis Streams
Now that the Redis store is set up, you can deploy the assets.
1. In your CLI window, navigate to the deploy directory
2. To deploy the publisher and two subscriber microservices, as well as the redis configuration you set up in the last step, run:
2. To deploy the publisher and three subscriber microservices, as well as the redis configuration you set up in the last step, run:
<!-- STEP
name: Deploy to k8s
@ -341,10 +346,12 @@ working_dir: deploy
expected_stdout_lines:
- "deployment.apps/node-subscriber created"
- "deployment.apps/python-subscriber created"
- "deployment.apps/csharp-subscriber created"
- "service/react-form created"
- "deployment.apps/react-form created"
- 'deployment "node-subscriber" successfully rolled out'
- 'deployment "python-subscriber" successfully rolled out'
- 'deployment "csharp-subscriber" successfully rolled out'
- 'deployment "react-form" successfully rolled out'
-->
@ -491,6 +498,7 @@ working_dir: deploy
expected_stdout_lines:
- 'deployment.apps "node-subscriber" deleted'
- 'deployment.apps "python-subscriber" deleted'
- 'deployment.apps "csharp-subscriber" deleted'
- 'service "react-form" deleted'
- 'deployment.apps "react-form" deleted'
- 'component.dapr.io "pubsub" deleted'
@ -575,80 +583,53 @@ Note: if `flush=True` is not set, logs will not appear when running `kubectl get
### C# message subscriber
Navigate to the `csharp-subscriber` directory and open `Startup.cs` and/or `MessageController.cs` , the code for the C# subscriber. We're exposing three API endpoints, this time using `Asp.Net Core`. first let's look at Startup.cs:
Navigate to the `csharp-subscriber` directory and open `Program.cs`, the code for the C# subscriber. We're exposing three API endpoints, this time using `Asp.Net Core 6 Minimal API`.
```csharp
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddDapr();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "csharp_subscriber", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "csharp_subscriber v1"));
}
app.UseRouting();
app.UseCloudEvents();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapSubscribeHandler();
endpoints.MapControllers();
});
}
```
Again, this is how you tell Dapr what topics in which pubsub component to subscribe to. In this case, subscribing to topics "A" and "B" and "C" of pubsub component named 'pubsub'. Messages of those topics are handled with these three routes:
```csharp
[ApiController]
public class MessageController : ControllerBase
using Dapr;
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();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
private readonly ILogger<MessageController> _logger;
public MessageController(ILogger<MessageController> logger)
{
_logger = logger;
}
[Topic("pubsub", "A")]
[HttpPost("A")]
public ActionResult TopicA(Dictionary<string, string> item)
{
_logger.LogInformation($"A: {item["message"]}");
return Ok();
}
[Topic("pubsub", "B")]
[HttpPost("B")]
public ActionResult TopicB(Dictionary<string, string> item)
{
_logger.LogInformation($"B: {item["message"]}");
return Ok();
}
[Topic("pubsub", "C")]
[HttpPost("C")]
public ActionResult TopicC(Dictionary<string, string> item)
{
_logger.LogInformation($"C: {item["message"]}");
return Ok();
}
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI();
}
// Dapr configurations
app.UseCloudEvents();
app.MapSubscribeHandler();
app.MapPost("/A", [Topic("pubsub", "A")] (ILogger<Program> logger, MessageEvent item) => {
logger.LogInformation($"{item.MessageType}: {item.Message}");
return Results.Ok();
});
app.MapPost("/B", [Topic("pubsub", "B")] (ILogger<Program> logger, MessageEvent item) => {
logger.LogInformation($"{item.MessageType}: {item.Message}");
return Results.Ok();
});
app.MapPost("/C", [Topic("pubsub", "C")] (ILogger<Program> logger, Dictionary<string, string> item) => {
logger.LogInformation($"{item["messageType"]}: {item["message"]}");
return Results.Ok();
});
app.Run();
internal record MessageEvent(string MessageType, string Message);
```
### React front end

View File

@ -0,0 +1,21 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 5009
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["csharp-subscriber.csproj", "./"]
RUN dotnet restore "csharp-subscriber.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "csharp-subscriber.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "csharp-subscriber.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "csharp-subscriber.dll"]

View File

@ -0,0 +1,42 @@
using Dapr;
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();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI();
}
// Dapr configurations
app.UseCloudEvents();
app.MapSubscribeHandler();
app.MapPost("/A", [Topic("pubsub", "A")] (ILogger<Program> logger, MessageEvent item) => {
logger.LogInformation($"{item.MessageType}: {item.Message}");
return Results.Ok();
});
app.MapPost("/B", [Topic("pubsub", "B")] (ILogger<Program> logger, MessageEvent item) => {
logger.LogInformation($"{item.MessageType}: {item.Message}");
return Results.Ok();
});
app.MapPost("/C", [Topic("pubsub", "C")] (ILogger<Program> logger, Dictionary<string, string> item) => {
logger.LogInformation($"{item["messageType"]}: {item["message"]}");
return Results.Ok();
});
app.Run();
internal record MessageEvent(string MessageType, string Message);

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.14.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="Dapr.AspNetCore" Version="1.7.0" />
</ItemGroup>
</Project>

View File

@ -20,7 +20,7 @@ spec:
spec:
containers:
- name: csharp-subscriber
image: dapriosamples/pubsub-csharp-subscriber:latest
image: ghcr.io/dapr/samples/pubsub-csharp-subscriber:latest
ports:
- containerPort: 5009
imagePullPolicy: Always