Closed ovidiaconescu closed 4 years ago
Hi, until this gets implemented, if you are in an asp.net core app:
Change IMqttServerConnectionValidator
for IMqttServerApplicationMessageInterceptor
public class InitializableMqttServerConnectionValidator : IMqttServerConnectionValidator
{
private IServiceProvider _serviceProvider;
public void Init(IServiceProvider serviceProvider)
{
if (_serviceProvider != null)
{
throw new InvalidOperationException("Can't init a second time!");
}
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public async Task ValidateConnectionAsync(MqttConnectionValidatorContext context)
{
if (_serviceProvider == null)
{
throw new Exception("Can't validate if Init not called");
}
using IServiceScope scope = _serviceProvider.CreateScope();
await scope.ServiceProvider.GetRequiredService<IMqttServerConnectionValidator>().ValidateConnectionAsync(context);
}
}
And in ConfigureServices
:
services.AddHostedMqttServer(t => t.WithDefaultEndpointPort(1883).WithConnectionValidator(new InitializableMqttServerConnectionValidator())
And in Configure
app.UseMqttServer(server =>
{
((InitializableMqttServerConnectionValidator)server.Options.ConnectionValidator).Init(app.ApplicationServices);
});
And don't forget to register a IMqttServerConnectionValidator
in your DI container!
But this is not how it should be implemented here. Ideally, the different services in the config should be DI resovled if not specified.
Yes please, I also need dependency injection for my custom application message interceptor. Right now I'm using this hack which is pretty ugly and produces a warning at compilation.
services.AddSingleton<IMqttServerApplicationMessageInterceptor, MyCustomApplicationMessageInterceptor>();
var serviceProvider = services.BuildServiceProvider();
var interceptorInstance = serviceProvider.GetService<IMqttServerApplicationMessageInterceptor>();
services
.AddHostedMqttServer(mqttServer => {
mqttServer.WithApplicationMessageInterceptor(interceptorInstance).WithoutDefaultEndpoint();
});
I second @ovidiaconescu's solution and this would also be ok, assuming it uses the dependency resolver to construct the application message interceptor.
services
.AddHostedMqttServer(mqttServer => {
mqttServer.WithApplicationMessageInterceptor<MyCustomApplicationMessageInterceptor>().WithoutDefaultEndpoint();
});
If you are using MQTTnet with AspNetCore, this library handles a similar use case https://github.com/Atlas-LiftTech/MQTTnet.AspNetCore.AttributeRouting. It works with the built-in dependency injection in AspNetCore and allows you to treat your MessageInterceptors as controller actions.
Just wanted to makes sure you are aware of the option.
Just wanted to makes sure you are aware of the option.
@avishnyak I wasn't aware of this, thank you. It looks interesting so I'll definitely give it a look.
Hello, is it possible to plug in a custom implementation of
IMqttServerApplicationMessageInterceptor
via Dependency Injection? The only example with this seems to be https://github.com/rafiulgits/IotHubIdeally, something like this would work best
services.AddScoped<IMqttServerApplicationMessageInterceptor, MessageInterceptor>();
instead of
Scoped seems to be the most used lifecycle as it would work with Entity Framework Core DbCodex which is also Scoped by default. This way the Interceptor would be able to access the database to validate clients and store messages.