Skip to content

Commit cd4c094

Browse files
authored
Merge pull request #5 from seikosantana/from-payload_parameter
[FromPayload] Support
2 parents 0f55395 + 12a47ca commit cd4c094

File tree

6 files changed

+86
-2
lines changed

6 files changed

+86
-2
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.Extensions.Logging;
3+
using MQTTnet.AspNetCore.Routing;
4+
using MQTTnet.AspNetCore.Routing.Attributes;
5+
6+
namespace ExampleServer.MqttControllers;
7+
8+
[MqttController]
9+
public class ViewModelController: MqttBaseController
10+
{
11+
private ILogger<ViewModelController> Logger { get; }
12+
13+
public ViewModelController(ILogger<ViewModelController> logger)
14+
{
15+
Logger = logger;
16+
}
17+
18+
[MqttRoute("viewmodel/{sender}")]
19+
public Task DeserializeViewModel(string sender, [FromPayload] SamplePayload payload)
20+
{
21+
Logger.LogInformation("{Sender} says {Message}", sender, payload.Message);
22+
return Accepted();
23+
}
24+
}
25+
26+
public class SamplePayload
27+
{
28+
public string Message { get; set; }
29+
}

ExampleServer/Startup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Linq;
2+
using System.Text.Json;
23
using Microsoft.AspNetCore.Builder;
34
using Microsoft.AspNetCore.Hosting;
45
using Microsoft.Extensions.Configuration;
@@ -29,6 +30,10 @@ public void ConfigureServices(IServiceCollection services)
2930

3031
// Identify and build routes for the current assembly
3132
services.AddMqttControllers();
33+
34+
// Use specific deserialization option for MQTT payload deserialization
35+
services.AddMqttDefaultJsonOptions(new JsonSerializerOptions(JsonSerializerDefaults.Web));
36+
3237
services
3338
.AddHostedMqttServerWithServices(s =>
3439
{
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Text.Json;
3+
4+
namespace MQTTnet.AspNetCore.Routing.Attributes;
5+
6+
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
7+
public class FromPayloadAttribute : Attribute
8+
{
9+
public FromPayloadAttribute()
10+
{
11+
12+
}
13+
}

Source/Extensions/ServiceCollectionExtensions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System;
77
using System.Reflection;
88
using System.Runtime.CompilerServices;
9+
using System.Text.Json;
910

1011
// This is needed to make internal classes visible to UnitTesting projects
1112
[assembly: InternalsVisibleTo("MQTTnet.AspNetCore.Routing.Tests, PublicKey=00240000048000009" +
@@ -38,6 +39,13 @@ public static IServiceCollection AddMqttControllers(this IServiceCollection serv
3839
return services;
3940
}
4041

42+
public static IServiceCollection AddMqttDefaultJsonOptions(this IServiceCollection services,
43+
JsonSerializerOptions options)
44+
{
45+
services.AddSingleton(new MqttDefaultJsonOptions(options));
46+
return services;
47+
}
48+
4149
public static void WithAttributeRouting(this MqttServer server, IServiceProvider svcProvider, bool allowUnmatchedRoutes = false)
4250
{
4351
var router = svcProvider.GetRequiredService<MqttRouter>();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Text.Json;
2+
3+
namespace MQTTnet.AspNetCore.Routing;
4+
5+
public class MqttDefaultJsonOptions
6+
{
7+
public JsonSerializerOptions SerializerOptions { get; }
8+
9+
public MqttDefaultJsonOptions(JsonSerializerOptions options)
10+
{
11+
SerializerOptions = options;
12+
}
13+
}

Source/Routing/MqttRouter.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Collections.Generic;
99
using System.Linq;
1010
using System.Reflection;
11+
using System.Text.Json;
1112
using System.Threading.Tasks;
1213

1314
#nullable enable
@@ -122,7 +123,10 @@ internal async Task OnIncomingApplicationMessage(IServiceProvider svcProvider, I
122123

123124
try
124125
{
125-
paramArray = parameters.Select(p => MatchParameterOrThrow(p, routeContext.Parameters)).ToArray();
126+
paramArray = parameters.Select(p =>
127+
MatchParameterOrThrow(p, routeContext.Parameters, controllerContext, svcProvider)
128+
)
129+
.ToArray();
126130

127131
await HandlerInvoker(routeContext.Handler, classInstance, paramArray).ConfigureAwait(false);
128132
}
@@ -174,8 +178,20 @@ private static Task HandlerInvoker(MethodInfo method, object instance, object?[]
174178
throw new InvalidOperationException($"Unsupported Action return type \"{method.ReturnType}\" on method {method.DeclaringType.FullName}.{method.Name}. Only void and {nameof(Task)} are allowed.");
175179
}
176180

177-
private static object? MatchParameterOrThrow(ParameterInfo param, IReadOnlyDictionary<string, object> availableParmeters)
181+
private static object? MatchParameterOrThrow(ParameterInfo param,
182+
IReadOnlyDictionary<string, object> availableParmeters, MqttControllerContext controllerContext,
183+
IServiceProvider serviceProvider)
178184
{
185+
if (param.IsDefined(typeof(FromPayloadAttribute), false))
186+
{
187+
JsonSerializerOptions? defaultOptions =
188+
serviceProvider.GetService<MqttDefaultJsonOptions>()?.SerializerOptions;
189+
return JsonSerializer.Deserialize(controllerContext.MqttContext.ApplicationMessage.Payload,
190+
param.ParameterType,
191+
defaultOptions
192+
);
193+
}
194+
179195
if (!availableParmeters.TryGetValue(param.Name, out object? value))
180196
{
181197
if (param.IsOptional)

0 commit comments

Comments
 (0)