Skip to content

Commit 91f9c40

Browse files
authored
Fix SkipSerialization leak (#6361)
1 parent 4330038 commit 91f9c40

File tree

2 files changed

+117
-2
lines changed

2 files changed

+117
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
namespace NServiceBus.AcceptanceTests.Core.Pipeline
2+
{
3+
using System;
4+
using System.Threading.Tasks;
5+
using AcceptanceTesting;
6+
using AcceptanceTesting.Customization;
7+
using EndpointTemplates;
8+
using NServiceBus.Pipeline;
9+
using NUnit.Framework;
10+
11+
public class When_skipping_serialization_with_nested_send : NServiceBusAcceptanceTest
12+
{
13+
[Test]
14+
public async Task Should_not_skip_serialization_for_nested_send()
15+
{
16+
var context = await Scenario.Define<Context>()
17+
.WithEndpoint<Sender>(e => e
18+
.When(s => s.Send(new MessageWithoutSerialization { SomeProperty = "Some property value" })))
19+
.WithEndpoint<Receiver>()
20+
.Done(c => c.NestedMessageReceived)
21+
.Run(TimeSpan.FromSeconds(15));
22+
23+
Assert.IsTrue(context.NestedMessageReceived, "the serialization should the nested message should not be skipped");
24+
Assert.AreEqual("Some property value for NestedMessage", context.NestedMessagePropertyValue, "the message sould be correctly serialized");
25+
Assert.IsFalse(context.MessageWithSkippedSerializationReceived, "NServiceBus should discard messages without a body");
26+
}
27+
28+
class Context : ScenarioContext
29+
{
30+
public bool MessageWithSkippedSerializationReceived { get; set; }
31+
public bool NestedMessageReceived { get; set; }
32+
public string NestedMessagePropertyValue { get; set; }
33+
}
34+
35+
class Sender : EndpointConfigurationBuilder
36+
{
37+
public Sender()
38+
{
39+
EndpointSetup<DefaultServer>(c =>
40+
{
41+
c.ConfigureTransport().Routing().RouteToEndpoint(typeof(NestedMessage).Assembly, Conventions.EndpointNamingConvention(typeof(Receiver)));
42+
c.Pipeline.Register(new SkipSerializationBehavior(), $"Skips serialization for {nameof(MessageWithoutSerialization)}");
43+
c.Pipeline.Register(new NestedSendBehavior(), $"Sends a {nameof(NestedMessage)} from the outgoing pipeline");
44+
});
45+
}
46+
47+
class SkipSerializationBehavior : Behavior<IOutgoingLogicalMessageContext>
48+
{
49+
public override Task Invoke(IOutgoingLogicalMessageContext context, Func<Task> next)
50+
{
51+
if (context.Message.MessageType == typeof(MessageWithoutSerialization))
52+
{
53+
context.SkipSerialization();
54+
}
55+
56+
return next();
57+
}
58+
}
59+
60+
class NestedSendBehavior : Behavior<IOutgoingPhysicalMessageContext>
61+
{
62+
public override async Task Invoke(IOutgoingPhysicalMessageContext context, Func<Task> next)
63+
{
64+
var logicalMessage = context.Extensions.Get<OutgoingLogicalMessage>();
65+
if (logicalMessage.MessageType != typeof(NestedMessage))
66+
{
67+
await context.Send(new NestedMessage { SomeProperty = "Some property value for NestedMessage" });
68+
}
69+
70+
await next();
71+
}
72+
}
73+
}
74+
75+
class Receiver : EndpointConfigurationBuilder
76+
{
77+
public Receiver() => EndpointSetup<DefaultServer>();
78+
79+
class MessageHandler : IHandleMessages<MessageWithoutSerialization>, IHandleMessages<NestedMessage>
80+
{
81+
Context testContext;
82+
83+
public MessageHandler(Context testContext)
84+
{
85+
this.testContext = testContext;
86+
}
87+
88+
public Task Handle(MessageWithoutSerialization message, IMessageHandlerContext context)
89+
{
90+
testContext.MessageWithSkippedSerializationReceived = true;
91+
return Task.FromResult(0);
92+
}
93+
94+
public Task Handle(NestedMessage message, IMessageHandlerContext context)
95+
{
96+
testContext.NestedMessageReceived = true;
97+
testContext.NestedMessagePropertyValue = message.SomeProperty;
98+
return Task.FromResult(0);
99+
}
100+
}
101+
}
102+
103+
public class MessageWithoutSerialization : IMessage
104+
{
105+
public string SomeProperty { get; set; }
106+
}
107+
108+
public class NestedMessage : IMessage
109+
{
110+
public string SomeProperty { get; set; }
111+
}
112+
}
113+
}

src/NServiceBus.Core/Serialization/SerializationContextExtensions.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public static class SerializationContextExtensions
1818
public static void SkipSerialization(this IOutgoingLogicalMessageContext context)
1919
{
2020
Guard.AgainstNull(nameof(context), context);
21-
context.Extensions.Set("MessageSerialization.Skip", true);
21+
22+
// Prefix the setting key with the current message id to prevent the setting from leaking to nested send operations for different messages
23+
context.Extensions.Set($"{context.MessageId}:MessageSerialization.Skip", true);
2224
}
2325

2426
/// <summary>
@@ -27,7 +29,7 @@ public static void SkipSerialization(this IOutgoingLogicalMessageContext context
2729
public static bool ShouldSkipSerialization(this IOutgoingLogicalMessageContext context)
2830
{
2931
Guard.AgainstNull(nameof(context), context);
30-
if (context.Extensions.TryGet("MessageSerialization.Skip", out bool shouldSkipSerialization))
32+
if (context.Extensions.TryGet($"{context.MessageId}:MessageSerialization.Skip", out bool shouldSkipSerialization))
3133
{
3234
return shouldSkipSerialization;
3335
}

0 commit comments

Comments
 (0)