Skip to content

Commit 74f15b1

Browse files
authored
Update to Aspire 13 (#916)
* Update to official versions and fix the build * Update to v7 RabbitMQ Remove some native AOT workarounds Convert to use artifacts output so the src directory isn't litered with bin/obj folders * Update to latest patch, including Aspire.Npgsql.EntityFrameworkCore.PostgreSQL
1 parent 1b2698c commit 74f15b1

File tree

9 files changed

+76
-93
lines changed

9 files changed

+76
-93
lines changed

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<ImplicitUsings>enable</ImplicitUsings>
1010
<!-- Temporarily disable security warnings for transitive packages. -->
1111
<NoWarn>NU1901;NU1902;NU1903;NU1904</NoWarn>
12+
<UseArtifactsOutput>true</UseArtifactsOutput>
1213
</PropertyGroup>
1314

1415
<!-- Enable OpenAI OpenTelemetry so OpenAI calls participate in tracing and metrics. -->

Directory.Build.targets

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,6 @@
66

77
<!-- Ensure individual warnings are shown when publishing -->
88
<TrimmerSingleWarn>false</TrimmerSingleWarn>
9-
<!-- But ignore the single warn files marked below to suppress their known warnings. -->
10-
<NoWarn>$(NoWarn);IL2104</NoWarn>
119
</PropertyGroup>
1210

13-
<Target Name="ConfigureTrimming"
14-
BeforeTargets="PrepareForILLink">
15-
<!-- Single warn the following assemblies, which have known warnings, so the warnings can be suppressed for now. -->
16-
<ItemGroup>
17-
<!-- https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/1410 is tracking fixing the one EventSource warning in RabbitMQ. -->
18-
<IlcArg Include="--singlewarnassembly:RabbitMQ.Client" />
19-
</ItemGroup>
20-
</Target>
21-
2211
</Project>

Directory.Packages.props

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,62 @@
22
<PropertyGroup>
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
44
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
5-
<AspnetVersion>10.0.0-preview.7.25380.108</AspnetVersion>
6-
<MicrosoftExtensionsVersion>10.0.0-preview.7.25380.108</MicrosoftExtensionsVersion>
7-
<AspireVersion>9.5.0</AspireVersion>
8-
<AspireUnstablePackagesVersion>9.5.0-preview.1.25474.7</AspireUnstablePackagesVersion>
5+
<AspnetVersion>10.0.0</AspnetVersion>
6+
<MicrosoftExtensionsVersion>10.0.0</MicrosoftExtensionsVersion>
7+
<AspireVersion>13.0.1</AspireVersion>
8+
<AspireUnstablePackagesVersion>13.0.0-preview.1.25560.3</AspireUnstablePackagesVersion>
99
<GrpcVersion>2.71.0</GrpcVersion>
1010
<DuendeVersion>7.3.1</DuendeVersion>
1111
<ApiVersioningVersion>8.1.0</ApiVersioningVersion>
1212
</PropertyGroup>
1313
<ItemGroup>
1414
<!-- Version together with Aspire -->
15-
<PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireVersion)" />
1615
<PackageVersion Include="Aspire.Hosting.Azure.CognitiveServices" Version="$(AspireVersion)" />
1716
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
1817
<PackageVersion Include="Aspire.Hosting.RabbitMQ" Version="$(AspireVersion)" />
1918
<PackageVersion Include="Aspire.Hosting.Redis" Version="$(AspireVersion)" />
20-
<PackageVersion Include="Aspire.Hosting.Yarp" Version="$(AspireUnstablePackagesVersion)" />
19+
<PackageVersion Include="Aspire.Hosting.Yarp" Version="$(AspireVersion)" />
2120
<PackageVersion Include="Aspire.Npgsql" Version="$(AspireVersion)" />
2221
<PackageVersion Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(AspireVersion)" />
2322
<PackageVersion Include="Aspire.RabbitMQ.Client" Version="$(AspireVersion)" />
2423
<PackageVersion Include="Aspire.StackExchange.Redis" Version="$(AspireVersion)" />
2524
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="$(AspireUnstablePackagesVersion)" />
26-
<PackageVersion Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.0-rc.1.25451.107">
25+
<PackageVersion Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.0">
2726
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2827
<PrivateAssets>all</PrivateAssets>
2928
</PackageVersion>
30-
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="$(AspireVersion)" />
31-
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery.Yarp" Version="$(AspireVersion)" />
29+
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="$(MicrosoftExtensionsVersion)" />
30+
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery.Yarp" Version="$(MicrosoftExtensionsVersion)" />
3231
<!-- Version together with Asp.Versioning -->
3332
<PackageVersion Include="Asp.Versioning.Http" Version="$(ApiVersioningVersion)" />
3433
<PackageVersion Include="Asp.Versioning.Http.Client" Version="$(ApiVersioningVersion)" />
3534
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="$(ApiVersioningVersion)" />
3635
<!-- Version together with ASP.NET -->
37-
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0-rc.1.25451.107" />
38-
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.0-rc.1.25451.107" />
39-
<PackageVersion Include="Microsoft.AspNetCore.Components.QuickGrid" Version="10.0.0-rc.1.25451.107" />
40-
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="10.0.0-rc.1.25451.107" />
41-
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.0-rc.1.25451.107" />
42-
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.0-rc.1.25451.107" />
43-
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0-rc.1.25451.107" />
44-
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-rc.1.25451.107" />
45-
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.0-rc.1.25451.107" />
46-
<PackageVersion Include="Microsoft.Extensions.Identity.Stores" Version="10.0.0-rc.1.25451.107" />
47-
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.9.0" />
36+
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
37+
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.0" />
38+
<PackageVersion Include="Microsoft.AspNetCore.Components.QuickGrid" Version="10.0.0" />
39+
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="10.0.0" />
40+
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.0" />
41+
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.0" />
42+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
43+
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
44+
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.0" />
45+
<PackageVersion Include="Microsoft.Extensions.Identity.Stores" Version="10.0.0" />
46+
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.0.0" />
4847
<PackageVersion Include="Microsoft.OpenApi" Version="2.3.2" />
4948
<PackageVersion Include="MSTest.TestFramework" Version="3.10.4" />
5049
<PackageVersion Include="MSTest.TestAdapter" Version="3.10.4" />
5150
<!-- Version together with EF -->
52-
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0-rc.1" />
53-
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0-rc.1.25451.107" />
51+
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
52+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0" />
5453
<PackageVersion Include="NSubstitute" Version="5.3.0" />
5554
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" />
5655
<PackageVersion Include="Pgvector" Version="0.3.2" />
5756
<PackageVersion Include="Pgvector.EntityFrameworkCore" Version="0.2.2" />
5857
<!-- Version together with runtime -->
59-
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.0-rc.1.25451.107" />
60-
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0-rc.1.25451.107" />
61-
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-rc.1.25451.107" />
58+
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.0" />
59+
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
60+
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
6261
<!-- Xabaril packages -->
6362
<PackageVersion Include="AspNetCore.HealthChecks.Uris" Version="9.0.0" />
6463
<!-- AI -->
@@ -89,7 +88,7 @@
8988
<PackageVersion Include="Dapper" Version="2.1.35" />
9089
<PackageVersion Include="FluentValidation" Version="12.0.0" />
9190
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="12.0.0" />
92-
<PackageVersion Include="Google.Protobuf" Version="3.32.1" />
91+
<PackageVersion Include="Google.Protobuf" Version="3.33.0" />
9392
<PackageVersion Include="Microsoft.Web.LibraryManager.Build" Version="3.0.71" />
9493
<PackageVersion Include="System.Reflection.TypeExtensions" Version="4.7.0" />
9594
<PackageVersion Include="xunit" Version="2.9.3" />

src/EventBusRabbitMQ/RabbitMQEventBus.cs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ public sealed class RabbitMQEventBus(
2626
private readonly EventBusSubscriptionInfo _subscriptionInfo = subscriptionOptions.Value;
2727
private IConnection _rabbitMQConnection;
2828

29-
private IModel _consumerChannel;
29+
private IChannel _consumerChannel;
3030

31-
public Task PublishAsync(IntegrationEvent @event)
31+
public async Task PublishAsync(IntegrationEvent @event)
3232
{
3333
var routingKey = @event.GetType().Name;
3434

@@ -37,22 +37,24 @@ public Task PublishAsync(IntegrationEvent @event)
3737
logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, routingKey);
3838
}
3939

40-
using var channel = _rabbitMQConnection?.CreateModel() ?? throw new InvalidOperationException("RabbitMQ connection is not open");
40+
using var channel = (await _rabbitMQConnection?.CreateChannelAsync()) ?? throw new InvalidOperationException("RabbitMQ connection is not open");
4141

4242
if (logger.IsEnabled(LogLevel.Trace))
4343
{
4444
logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id);
4545
}
4646

47-
channel.ExchangeDeclare(exchange: ExchangeName, type: "direct");
47+
await channel.ExchangeDeclareAsync(
48+
exchange: ExchangeName,
49+
type: "direct");
4850

4951
var body = SerializeMessage(@event);
5052

5153
// Start an activity with a name following the semantic convention of the OpenTelemetry messaging specification.
5254
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/messaging/messaging-spans.md
5355
var activityName = $"{routingKey} publish";
5456

55-
return _pipeline.Execute(() =>
57+
await _pipeline.Execute(async () =>
5658
{
5759
using var activity = _activitySource.StartActivity(activityName, ActivityKind.Client);
5860

@@ -70,9 +72,10 @@ public Task PublishAsync(IntegrationEvent @event)
7072
contextToInject = Activity.Current.Context;
7173
}
7274

73-
var properties = channel.CreateBasicProperties();
74-
// persistent
75-
properties.DeliveryMode = 2;
75+
var properties = new BasicProperties()
76+
{
77+
DeliveryMode = DeliveryModes.Persistent
78+
};
7679

7780
static void InjectTraceContextIntoBasicProperties(IBasicProperties props, string key, string value)
7881
{
@@ -91,14 +94,12 @@ static void InjectTraceContextIntoBasicProperties(IBasicProperties props, string
9194

9295
try
9396
{
94-
channel.BasicPublish(
97+
await channel.BasicPublishAsync(
9598
exchange: ExchangeName,
9699
routingKey: routingKey,
97100
mandatory: true,
98101
basicProperties: properties,
99102
body: body);
100-
101-
return Task.CompletedTask;
102103
}
103104
catch (Exception ex)
104105
{
@@ -130,7 +131,7 @@ public void Dispose()
130131

131132
private async Task OnMessageReceived(object sender, BasicDeliverEventArgs eventArgs)
132133
{
133-
static IEnumerable<string> ExtractTraceContextFromBasicProperties(IBasicProperties props, string key)
134+
static IEnumerable<string> ExtractTraceContextFromBasicProperties(IReadOnlyBasicProperties props, string key)
134135
{
135136
if (props.Headers.TryGetValue(key, out var value))
136137
{
@@ -176,7 +177,7 @@ static IEnumerable<string> ExtractTraceContextFromBasicProperties(IBasicProperti
176177
// Even on exception we take the message off the queue.
177178
// in a REAL WORLD app this should be handled with a Dead Letter Exchange (DLX).
178179
// For more information see: https://www.rabbitmq.com/dlx.html
179-
_consumerChannel.BasicAck(eventArgs.DeliveryTag, multiple: false);
180+
await _consumerChannel.BasicAckAsync(eventArgs.DeliveryTag, multiple: false);
180181
}
181182

182183
private async Task ProcessEvent(string eventName, string message)
@@ -224,9 +225,8 @@ private byte[] SerializeMessage(IntegrationEvent @event)
224225

225226
public Task StartAsync(CancellationToken cancellationToken)
226227
{
227-
// Messaging is async so we don't need to wait for it to complete. On top of this
228-
// the APIs are blocking, so we need to run this on a background thread.
229-
_ = Task.Factory.StartNew(() =>
228+
// Messaging is async so we don't need to wait for it to complete.
229+
_ = Task.Factory.StartNew(async () =>
230230
{
231231
try
232232
{
@@ -243,21 +243,24 @@ public Task StartAsync(CancellationToken cancellationToken)
243243
logger.LogTrace("Creating RabbitMQ consumer channel");
244244
}
245245

246-
_consumerChannel = _rabbitMQConnection.CreateModel();
246+
_consumerChannel = await _rabbitMQConnection.CreateChannelAsync();
247247

248-
_consumerChannel.CallbackException += (sender, ea) =>
248+
_consumerChannel.CallbackExceptionAsync += (sender, ea) =>
249249
{
250250
logger.LogWarning(ea.Exception, "Error with RabbitMQ consumer channel");
251+
return Task.CompletedTask;
251252
};
252253

253-
_consumerChannel.ExchangeDeclare(exchange: ExchangeName,
254-
type: "direct");
254+
await _consumerChannel.ExchangeDeclareAsync(
255+
exchange: ExchangeName,
256+
type: "direct");
255257

256-
_consumerChannel.QueueDeclare(queue: _queueName,
257-
durable: true,
258-
exclusive: false,
259-
autoDelete: false,
260-
arguments: null);
258+
await _consumerChannel.QueueDeclareAsync(
259+
queue: _queueName,
260+
durable: true,
261+
exclusive: false,
262+
autoDelete: false,
263+
arguments: null);
261264

262265
if (logger.IsEnabled(LogLevel.Trace))
263266
{
@@ -266,16 +269,16 @@ public Task StartAsync(CancellationToken cancellationToken)
266269

267270
var consumer = new AsyncEventingBasicConsumer(_consumerChannel);
268271

269-
consumer.Received += OnMessageReceived;
272+
consumer.ReceivedAsync += OnMessageReceived;
270273

271-
_consumerChannel.BasicConsume(
274+
await _consumerChannel.BasicConsumeAsync(
272275
queue: _queueName,
273276
autoAck: false,
274277
consumer: consumer);
275278

276279
foreach (var (eventName, _) in _subscriptionInfo.EventTypes)
277280
{
278-
_consumerChannel.QueueBind(
281+
await _consumerChannel.QueueBindAsync(
279282
queue: _queueName,
280283
exchange: ExchangeName,
281284
routingKey: eventName);

src/EventBusRabbitMQ/RabbitMqDependencyInjectionExtensions.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using eShop.EventBusRabbitMQ;
22
using Microsoft.Extensions.DependencyInjection;
3-
using Microsoft.Extensions.Configuration;
4-
using System.Diagnostics.CodeAnalysis;
53

64
namespace Microsoft.Extensions.Hosting;
75

@@ -16,18 +14,11 @@ public static class RabbitMqDependencyInjectionExtensions
1614

1715
private const string SectionName = "EventBus";
1816

19-
[UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode",
20-
Justification = "EventBusOptions is a simple POCO with public properties that are safe for trimming.")]
21-
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode",
22-
Justification = "EventBusOptions is a simple POCO with public properties that are safe for AOT.")]
2317
public static IEventBusBuilder AddRabbitMqEventBus(this IHostApplicationBuilder builder, string connectionName)
2418
{
2519
ArgumentNullException.ThrowIfNull(builder);
2620

27-
builder.AddRabbitMQClient(connectionName, configureConnectionFactory: factory =>
28-
{
29-
((ConnectionFactory)factory).DispatchConsumersAsync = true;
30-
});
21+
builder.AddRabbitMQClient(connectionName);
3122

3223
// RabbitMQ.Client doesn't have built-in support for OpenTelemetry, so we need to add it ourselves
3324
builder.Services.AddOpenTelemetry()

src/eShop.AppHost/Extensions.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Aspire.Hosting.Lifecycle;
1+
using Aspire.Hosting.Eventing;
2+
using Aspire.Hosting.Lifecycle;
23
using Aspire.Hosting.Yarp;
34
using Aspire.Hosting.Yarp.Transforms;
45
using Yarp.ReverseProxy.Configuration;
@@ -20,21 +21,26 @@ internal static class Extensions
2021
/// </summary>
2122
public static IDistributedApplicationBuilder AddForwardedHeaders(this IDistributedApplicationBuilder builder)
2223
{
23-
builder.Services.TryAddLifecycleHook<AddForwardHeadersHook>();
24+
builder.Services.TryAddEventingSubscriber<AddForwardHeadersSubscriber>();
2425
return builder;
2526
}
2627

27-
private class AddForwardHeadersHook : IDistributedApplicationLifecycleHook
28+
private class AddForwardHeadersSubscriber : IDistributedApplicationEventingSubscriber
2829
{
29-
public Task BeforeStartAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
30+
public Task SubscribeAsync(IDistributedApplicationEventing eventing, DistributedApplicationExecutionContext executionContext, CancellationToken cancellationToken)
3031
{
31-
foreach (var p in appModel.GetProjectResources())
32+
eventing.Subscribe<BeforeStartEvent>((@event, ct) =>
3233
{
33-
p.Annotations.Add(new EnvironmentCallbackAnnotation(context =>
34+
foreach (var p in @event.Model.GetProjectResources())
3435
{
35-
context.EnvironmentVariables["ASPNETCORE_FORWARDEDHEADERS_ENABLED"] = "true";
36-
}));
37-
}
36+
p.Annotations.Add(new EnvironmentCallbackAnnotation(context =>
37+
{
38+
context.EnvironmentVariables["ASPNETCORE_FORWARDEDHEADERS_ENABLED"] = "true";
39+
}));
40+
}
41+
42+
return Task.CompletedTask;
43+
});
3844

3945
return Task.CompletedTask;
4046
}

src/eShop.AppHost/eShop.AppHost.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
2-
<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.0" />
1+
<Project Sdk="Aspire.AppHost.Sdk/13.0.0">
32

43
<PropertyGroup>
54
<OutputType>Exe</OutputType>
@@ -10,7 +9,6 @@
109
</PropertyGroup>
1110

1211
<ItemGroup>
13-
<PackageReference Include="Aspire.Hosting.AppHost" />
1412
<PackageReference Include="Aspire.Hosting.RabbitMQ" />
1513
<PackageReference Include="Aspire.Hosting.Redis" />
1614
<PackageReference Include="Aspire.Hosting.PostgreSQL" />

tests/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
2-
<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.0" />
1+
<Project Sdk="Aspire.AppHost.Sdk/13.0.0">
32

43
<PropertyGroup>
54
<TargetFramework>net10.0</TargetFramework>
@@ -9,7 +8,6 @@
98

109
<ItemGroup>
1110
<PackageReference Include="Asp.Versioning.Http.Client" />
12-
<PackageReference Include="Aspire.Hosting.AppHost" />
1311
<PackageReference Include="Aspire.Hosting.PostgreSQL" />
1412
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
1513
<PackageReference Include="Microsoft.AspNetCore.TestHost" />

0 commit comments

Comments
 (0)