Skip to content

Commit 6711dcc

Browse files
authored
Weekly Legacy docs review (#7853)
* Remove custom logger sample * Legacy docs review
1 parent acf50af commit 6711dcc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+122
-1067
lines changed

nservicebus/best-practices.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Best practices
33
summary: An assortment of best practices presented as DO, DO NOT, and CONSIDER.
4-
reviewed: 2024-01-05
4+
reviewed: 2025-10-03
55
isLearningPath: true
66
---
77

@@ -13,9 +13,9 @@ This article presents recommendations to keep in mind when designing a system us
1313

1414
Multiple message handlers can be combined inside a single logical endpoint. However, these handlers all share a single message queue for different types of messages.
1515

16-
The endpoint is the fundamental unit of scale for an NServiceBus system. If one message handler has much higher throughput requirements, it can only be independently scaled if it exists in an endpoint by itself. In separate endpoints, only the message handler that has the unique scalability requirements has to be scaled out.
16+
The endpoint is the fundamental unit of scale for an NServiceBus system. If one message handler has much higher throughput requirements, it can only be independently scaled if it exists in an endpoint by itself. With separate endpoints, only the message handler that has the unique scalability requirements has to be scaled out.
1717

18-
The endpoint is also the fundamental unit of deployment for an NServcieBus system. That means that the entire endpoint must be redeployed if a fix is required for one message handler. The fewer message handlers in each endpoint, the less likely any individual deployment is to cause a problem in the system since the whole system does not have to be redeployed on every change.
18+
The endpoint is also the fundamental unit of deployment for an NServiceBus system. That means that the entire endpoint must be redeployed if a fix is required for one message handler. The fewer message handlers in each endpoint, the less likely any individual deployment is to cause a problem in the system since the whole system does not have to be redeployed on every change.
1919

2020
### :heavy_check_mark: **CONSIDER grouping message handlers by SLA**
2121

@@ -43,11 +43,11 @@ Meanwhile, a custom abstraction makes the NServiceBus documentation less effecti
4343

4444
It is best to embrace the asynchronous nature of NServiceBus messages and not use an asynchronous message (or a pair of messages in a request/reply scenario) for synchronous communication, especially when the scenario expects an answer to be available _right now_. This is especially important with queries: [messaging should not be used for queries](https://web.archive.org/web/20211205190919/http://andreasohlund.net/2010/04/22/messaging-shouldnt-be-used-for-queries/).
4545

46-
When a previously-defined user interface demands an immediate response, such as inserting a new item into a grid and then immediately refreshing the grid to include the new item, the [client-side callbacks package](/nservicebus/messaging/callbacks.md) can be used, but this should be considered a crutch until a more [task- or command-focused UI](https://cqrs.wordpress.com/documents/task-based-ui/) can replace it.
46+
When a previously defined user interface demands an immediate response, such as inserting a new item into a grid and then immediately refreshing the grid to include the new item, the [client-side callbacks package](/nservicebus/messaging/callbacks.md) can be used, but this should be considered a temporary workaround until a more [task- or command-focused UI](https://cqrs.wordpress.com/documents/task-based-ui/) can replace it.
4747

4848
### :x: **DO NOT create a messaging endpoint for every single web request**
4949

50-
NServiceBus does a lot of work when it first starts up, scanning through assemblies to find the types of messages and message handlers, establishing communication with the messaging infrastructure, and ensuring that everything is optimized to run quickly for the duration of the endpoint's life. Do not repeat all this work on every web request just to send a single message and then shut down.
50+
NServiceBus does a lot of work when it first starts up, including scanning through assemblies to find the types of messages and message handlers, establishing communication with the messaging infrastructure, and ensuring that everything is optimized to run quickly for the duration of the endpoint's life. Do not repeat all this work on every web request just to send a single message and then shut down.
5151

5252
An NServiceBus endpoint is designed to be a long-lived object that persists throughout the application process. Once the `IMessageSession` is created, use dependency injection to inject it into controllers or wherever else it is needed. If necessary, assign the `IMessageSession` to a global variable.
5353

@@ -63,7 +63,7 @@ Asynchronous messaging (e.g., NServiceBus) is **not** a good solution for data d
6363

6464
Message handlers should be simple and focused on only the business code needed to handle the message. Infrastructure code for logging, exception management, timing, auditing, authorization, unit of work, message signing/encryption, etc, should not be included in a message handler.
6565

66-
Instead, implement this functionality separately in a [message pipeline behavior](/nservicebus/pipeline/manipulate-with-behaviors.md), which enables inserting additional functionality into the NServiceBus message processing pipeline, similar to an ASP.NET ActionFilter.
66+
Instead, implement this functionality separately in a [message pipeline behavior](/nservicebus/pipeline/manipulate-with-behaviors.md), which enables inserting additional functionality into the NServiceBus message processing pipeline.
6767

6868
For a high-level overview of infrastructure concerns and behaviors, see the blog post [Infrastructure soup](https://particular.net/blog/infrastructure-soup).
6969

@@ -98,21 +98,17 @@ Message queues are long-lasting and durable. Occasionally connected clients, suc
9898

9999
For occasionally connected clients, consider another communication medium, such as in the [Near real-time transient clients sample](/samples/near-realtime-clients/), which communicates with clients using [SignalR](https://dotnet.microsoft.com/apps/aspnet/signalr).
100100

101-
### :heavy_check_mark: **CONSIDER [identifying message types using conventions](/nservicebus/messaging/unobtrusive-mode.md) to make upgrading to new versions of NServiceBus easier**
101+
### :heavy_check_mark: **Consider using shared message assemblies that reference [NServiceBus.MessageInterfaces](https://www.nuget.org/packages/NServiceBus.MessageInterfaces) to make upgrading to new versions of NServiceBus easier**
102102

103-
By default, NServiceBus will identify classes implementing `ICommand` as commands, `IEvent` as events, and `IMessage` as other types of messages, such as replies. This is quick and easy but also causes message projects to depend on the NServiceBus NuGet package.
103+
In a complex system, it's useful to be able to upgrade one endpoint at a time. Message assemblies are shared between multiple endpoints. If these assemblies reference the NServiceBus NuGet package directly, they can cause challenges during upgrades when one endpoint using a message assembly has upgraded to the next major version but the other has not.
104104

105-
In a complex system, it's useful to be able to upgrade one endpoint at a time. Message assemblies are shared between multiple endpoints, which can cause challenges during upgrades when one endpoint using a message assembly has upgraded to the next major version but the other has not.
106-
107-
These versioning problems can be addressed using [unobtrusive-mode messages](/nservicebus/messaging/unobtrusive-mode.md) by defining [message conventions](/nservicebus/messaging/conventions.md) independent of the `ICommand`/`IEvent`/`IMessage` interfaces.
108-
109-
These conventions can even be [encapsulated in a class](/nservicebus/messaging/conventions.md#encapsulated-conventions), and many can be used within one endpoint so that messages from multiple teams who have made different choices on message conventions can be used together.
105+
To solve this, message assemblies should instead reference the [`NServiceBus.MessageInterfaces` package](/samples/message-assembly-sharing/) which has no dependency on the NServiceBus package.
110106

111107
## System monitoring
112108

113-
### :heavy_check_mark: **DO install the [Heartbeats plugin](/monitoring/heartbeats/) in all endpoints to monitor for endpoint health**
109+
### :heavy_check_mark: **DO install the [Heartbeat plugin](/monitoring/heartbeats/) in all endpoints to monitor for endpoint health**
114110

115-
The Heartbeats plugin sends a message to [ServiceControl](/servicecontrol/) at regular intervals to demonstrate that the process is not only executing (which would be provided by any suite of system monitoring tools) but is also capable of interacting with the message transport.
111+
The Heartbeat plugin sends a message to [ServiceControl](/servicecontrol/) at regular intervals to demonstrate that the process is not only executing (which would be provided by any suite of system monitoring tools) but is also capable of interacting with the message transport.
116112

117113
If ServiceControl stops receiving heartbeat messages from an endpoint, that endpoint will be shown as [inactive in ServicePulse](/monitoring/heartbeats/in-servicepulse.md). In addition, ServiceControl will publish a [`HeartbeatStopped` event](/monitoring/heartbeats/notification-events.md) so that operations staff can be notified and respond.
118114

nservicebus/compliance/business-continuity.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Business continuity and disaster recovery procedures
33
summary: Particular Software business continuity and disaster recovery procedures
4-
reviewed: 2024-01-10
4+
reviewed: 2025-10-03
55
---
66

77
This document describes Particular Software business continuity and disaster recovery procedures.

samples/dependency-injection/externally-managed-mode/Core_10/Sample/Greeter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
public class Greeter
44
{
5-
private static readonly ILog log = LogManager.GetLogger<Greeter>();
5+
static readonly ILog log = LogManager.GetLogger<Greeter>();
66

77
public void SayHello()
88
{

samples/dependency-injection/externally-managed-mode/Core_10/Sample/MessageSender.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
using System.Threading.Tasks;
2-
using NServiceBus;
3-
4-
#region InjectingMessageSession
1+
#region InjectingMessageSession
52
public class MessageSender(IMessageSession messageSession)
63
{
74
public Task SendMessage()

samples/dependency-injection/externally-managed-mode/Core_10/Sample/MyHandler.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
using System.Threading.Tasks;
2-
using NServiceBus;
3-
#region InjectingDependency
4-
public class MyHandler(Greeter greeter) :
5-
IHandleMessages<MyMessage>
1+
#region InjectingDependency
2+
public class MyHandler(Greeter greeter) : IHandleMessages<MyMessage>
63
{
74
public Task Handle(MyMessage message, IMessageHandlerContext context)
85
{
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
using NServiceBus;
2-
3-
public record MyMessage : IMessage;
1+
public record MyMessage : IMessage;
Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,38 @@
1-
using System;
2-
using System.Threading.Tasks;
31
using Microsoft.Extensions.DependencyInjection;
4-
using NServiceBus;
52

6-
static class Program
7-
{
8-
static async Task Main()
9-
{
10-
Console.Title = "ExternallyManagedContainer";
3+
Console.Title = "ExternallyManagedContainer";
114

12-
var endpointConfiguration = new EndpointConfiguration("Sample");
13-
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
14-
endpointConfiguration.UseTransport(new LearningTransport());
5+
var endpointConfiguration = new EndpointConfiguration("Sample");
6+
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
7+
endpointConfiguration.UseTransport(new LearningTransport());
158

16-
#region ContainerConfiguration
9+
#region ContainerConfiguration
1710

18-
// ServiceCollection is provided by Microsoft.Extensions.DependencyInjection
19-
var serviceCollection = new ServiceCollection();
11+
// ServiceCollection is provided by Microsoft.Extensions.DependencyInjection
12+
var serviceCollection = new ServiceCollection();
2013

21-
// most dependencies may now be registered
22-
serviceCollection.AddSingleton<Greeter>();
23-
serviceCollection.AddSingleton<MessageSender>();
14+
// most dependencies may now be registered
15+
serviceCollection.AddSingleton<Greeter>();
16+
serviceCollection.AddSingleton<MessageSender>();
2417

25-
// EndpointWithExternallyManagedContainer.Create accepts an IServiceCollection,
26-
// which is inherited by ServiceCollection
27-
var endpointWithExternallyManagedContainer = EndpointWithExternallyManagedContainer
28-
.Create(endpointConfiguration, serviceCollection);
18+
// EndpointWithExternallyManagedContainer.Create accepts an IServiceCollection,
19+
// which is inherited by ServiceCollection
20+
var endpointWithExternallyManagedContainer = EndpointWithExternallyManagedContainer
21+
.Create(endpointConfiguration, serviceCollection);
2922

30-
// if IMessageSession is required as dependency, it may now be registered
31-
serviceCollection.AddSingleton(p => endpointWithExternallyManagedContainer.MessageSession.Value);
23+
// if IMessageSession is required as dependency, it may now be registered
24+
serviceCollection.AddSingleton(p => endpointWithExternallyManagedContainer.MessageSession.Value);
3225

33-
#endregion
26+
#endregion
3427

35-
using (var serviceProvider = serviceCollection.BuildServiceProvider())
36-
{
37-
var endpoint = await endpointWithExternallyManagedContainer.Start(serviceProvider);
28+
using var serviceProvider = serviceCollection.BuildServiceProvider();
3829

39-
var sender = serviceProvider.GetRequiredService<MessageSender>();
40-
await sender.SendMessage();
30+
var endpoint = await endpointWithExternallyManagedContainer.Start(serviceProvider);
4131

42-
Console.WriteLine("Press any key to exit");
43-
Console.ReadKey();
44-
await endpoint.Stop();
45-
}
46-
}
47-
}
32+
var sender = serviceProvider.GetRequiredService<MessageSender>();
33+
await sender.SendMessage();
34+
35+
Console.WriteLine("Press any key to exit");
36+
Console.ReadKey();
37+
38+
await endpoint.Stop();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2+
23
<PropertyGroup>
34
<TargetFramework>net10.0</TargetFramework>
45
<OutputType>Exe</OutputType>
6+
<ImplicitUsings>enable</ImplicitUsings>
57
<LangVersion>14.0</LangVersion>
68
</PropertyGroup>
9+
710
<ItemGroup>
811
<PackageReference Include="NServiceBus" Version="10.0.0-alpha.1" />
912
</ItemGroup>
13+
1014
</Project>

samples/dependency-injection/externally-managed-mode/Core_8/Sample/Greeter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
public class Greeter
44
{
5-
private static readonly ILog log = LogManager.GetLogger<Greeter>();
5+
static readonly ILog log = LogManager.GetLogger<Greeter>();
66

77
public void SayHello()
88
{

samples/dependency-injection/externally-managed-mode/Core_8/Sample/MessageSender.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
using System.Threading.Tasks;
2-
using NServiceBus;
3-
4-
#region InjectingMessageSession
5-
public class MessageSender
1+
#region InjectingMessageSession
2+
public class MessageSender(IMessageSession messageSession)
63
{
7-
private readonly IMessageSession messageSession;
8-
9-
public MessageSender(IMessageSession messageSession) =>
10-
this.messageSession = messageSession;
11-
124
public Task SendMessage()
135
{
146
var myMessage = new MyMessage();

0 commit comments

Comments
 (0)