how to use GetConnectedClientsAsync from MQTTnet.Server in asp.net core - asp.net-core

I can host mqtt broker with MQTTnet nuget in asp.net core 2.2 by following code. I just want to show list of connected cliend in my controller and I found that GetConnectedClientsAsync method can be used. But I don't know how to use in core 2.2. Any suggestion.
In ConfigureServices
var mqttServerOption = new MqttServerOptionsBuilder()
.WithDefaultEndpointPort(6261)
.WithConnectionValidator(Mqtt.connectionValidator.validator)
.Build();
services.AddHostedMqttServer(mqttServerOption)
.AddMqttConnectionHandler()
.AddConnections()
.AddMqttTcpServerAdapter();
In Configure
app.UseMqttEndpoint();

finally found the solution.
just added controller constructor
private readonly MQTTnet.AspNetCore.MqttHostedServer mqttHostedServer;
public testController(MQTTnet.AspNetCore.MqttHostedServer mqttHostedServer)
{
this.mqttHostedServer = mqttHostedServer;
}
and I can use it now.
var clients = await mqttHostedServer.GetClientStatusAsync();

Related

Azure Application Insight wrong shows URL in logs for ASP.NET Core 6 Web API application with API versioning

I have an ASP.NET Web API application running on .NET 4.8. In this app, I'm using standard Microsoft API versioning from Microsoft.AspNet.WebApi.Versioning and Microsoft.AspNet.WebApi.Versioning.ApiExplorer.
For instance:
[ApiVersionExtended(SupportedApiVersions.V9)]
[RoutePrefix("v{version:apiVersion}/telemetry")]
public sealed class TelemetryController : ApiController
{
where ApiVersionExtended - my filter. In Azure Application Insight requests to my API are shown with the correct version. For instance:
But after migration to .NET 6, I lost the correct version number in AI logs, for instance:
My code has several changes after migration to .NET 6
[ApiController]
[AllowAnonymous]
[ApiVersionExtended]
[Route("v{version:apiVersion}/telemetry")]
public sealed class TelemetryController : ApiController
{
[HttpGet("ipInfo")]
public async Task<IActionResult> GetIpInfoAsync(CancellationToken cancellationToken)
{
/* some code here */
}
}
I can't find the analog [RoutePrefix] attribute in .NET 6.
Might someone know what the reason for this issue is? And how I can fix it?
As suggested by #Peter Bons, this can be the issue with your existing Nuget Package.
The Nuget Package required to Implement API Versioning in .NET 6 Core Web API is Microsoft.AspNetCore.Mvc.Versioning
Install Microsoft.AspNetCore.Mvc.Versioning Nuget Package
In Program.cs add the below services
To add versioning for WebAPI
builder.Services.AddApiVersioning(opt =>
{
opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(2, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("x-api-version"));
});
To Add versioning with Swagger, add the below services
builder.Services.AddSwaggerGen(Options => Options.SwaggerDoc("v1", new OpenApiInfo { Title = "Audit Self Serve platform", Version = "v1" }));
Use MapToApiVersion attribute to assign each action to a distinct version
[MapToApiVersion("1.0")]
[HttpGet]
OutPut:

Add Blazor Client to ASP .Net Core Web API (.NET 6)

I was wondering if there was a specific way to add a Blazor front end to an ASP .NET Core project. I know when creating an Blazor WebAssembly App there is the option to select ASP.Net Core Hosted and it would create a template, but I would like to add the client to the host manually.
Specifically, I've been looking at this ASP.Net to ASP.Net Core tutorial here and would like to add a Blazor front-end to the ASP.NET Core Web API project that is created.
Sorry in advance if the question isn't clear, this is my first time doing this sort of project.
If you want to add the API to the host manually you can create an ASP.NET Core Web API project. Create your post/get/ect controllers in the Web API, and in the Blazor Project inject an HttpClient with a BaseUri that points at your Web API controllers.
This is how I set mine up too. I keep all my components and services separate in class library and razor library projects. Let me know if you need further assistance.
Update
Seems like their might be some confusion on the project layout. For this example I named my Blazor Server App BlazorServerFrontEnd. I named my ASP.NET Core Web API BlazorServerBackEnd. I created mine on .NET Core 6.0. It doesn't use a Startup.cs like 3.1. Instead everything is done in the Program.cs file.
BlazorServerBackEnd (Web Api) will not have services.AddServerSideBlazor() like our BlazorServerFrontEnd (Blazor Server App). If you're seeing this in both projects you probably selected the wrong type. When you run BlazorServerBackEnd (Web Api) you'll see it has one controller built in (Controllers/WeatherForecastController.cs).
BlazorServerFrontEnd (Blazor Server App) will have services.AddServerSideBlazor(). You'll see in Data folder there is also a WeatherForecatService.cs. When you look at the service it doesn't connect to any Api. The service just grabs the data from a hardcoded readonly string[].
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
This is what we need to change. Instead of the data being fetched from within BlazorServerFrontEnd (Blazor Server App) we want to connect to our BlazorServerBackEnd (Web Api). Open up Program.cs in the BlazorServerFrontEnd (Blazor Server App) and change the injected WeatherForecastService from a Singleton to an HttpClient.
//builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddHttpClient<WeatherForecastService>(client =>
{
// Path pointing to BlazorServerBackEnd (Web Api) baseUri
client.BaseAddress = new Uri("https://localhost:7246/");
});
Open up WeatherForecastService.cs in the BlazorServerFrontEnd (Blazor Server App) and add a constructor to inject our HttpClient that we just setup. We'll use the HttpClient to connect to our BlazorServerBackEnd (Web Api) using _httpClient.GetAsync("WeatherForecast"). Now it looks like this;
public class WeatherForecastService
{
private readonly HttpClient _httpClient;
public WeatherForecastService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
var response = await _httpClient.GetAsync("WeatherForecast");
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
WeatherForecast[] forecasts = JsonConvert.DeserializeObject<WeatherForecast[]>(json);
return forecasts;
}
return null;
}
}
Please keep in mind this is a very brief example to get you on your feet. Ideally you'll want to have an interface for your services, and you'll want to inject the interface into your pages instead of the class. So in the real world it would look more like this;
builder.Services.AddHttpClient<IWeatherForecastService, WeatherForecastService>(client =>
{
// Path pointing to BlazorServerBackEnd (Web Api) baseUri
client.BaseAddress = new Uri("https://localhost:7246/");
});
And you would be injecting your interface into the page like so;
#inject IWeatherForecastService ForecastService
I also recommend separating components, services, controllers, models ect. into seperate razor/class libraries. Keep everything very loosely coupled. This will make it easy for you to port your application over to something like a MAUI or Windows Forms App BlazorWebView.
P.S. Swagger comes built into the Web Api project. It is very useful when developing and debugging. I would recommend familiarizing yourself with it if your new.

Convert use of Membership to something that will work in .NET Core for WCF service calls

I have some legacy framework code that calls a service that I need to replicate in a .NET Core 3.1 solution. The code uses a client built by adding a web reference (ImageService). The code authenticates the user using Membership and sets an authentication cookie that is used by the execution of client methods.
The method below is what I need to replicate in the Core solution. I've created a client in the .NET Core solution also using the WCF web reference. What do I need to do/use to replicate the functionality of the code below?
private static void setImageService(string host, string userId, string password) {
ImageService.ImageService _imageServiceSoapClient = new ImageService.ImageService();
((ClientFormsAuthenticationMembershipProvider) Membership.Provider).ServiceUri = string.Format("https://{0}/ImageService/Authentication_JSON_AppService.axd", host);
((ClientRoleProvider) Roles.Provider).ServiceUri = string.Format("https://{0}/ImageService/Role_JSON_AppService.axd", host);
bool validateUser = Membership.ValidateUser(userId, password);
if (validateUser) {
AppDomain.CurrentDomain.SetThreadPrincipal(Thread.CurrentPrincipal);
} else {
throw new InvalidCredentialException(string.Format("User {0} not authenticated", userId));
}
_imageServiceSoapClient.CookieContainer = ((ClientFormsIdentity) Thread.CurrentPrincipal.Identity).AuthenticationCookies;
}

Can we Host ASP.NET SignalR v2.4.1 in an ASP.NETCORE App?

I have a situation where my codebase is stuck in .Net 4.7.2 for now but I need to push some notifications on a Website which is built on Asp.Core 2.2.
Across the system we use SignalR 2.4.1 but it is completely re-written in .Net Core.
I tried hosting it in the same app without success. Owin does not seem to be happy.
Has anyone had any success with it or has any suggestion?
There has to be a way for projects migrating from .Net to Core.
Thanks
Ok so after along night I got a solution to this issue.
First just to make my setup clear.
There is an API project targetting .Net 4.7.2 which is broadcasting some messages via a SignalR 2.4.1 Hub.
There are some other Asp.Net 4.7.2 Projects consuming those Hubs which are working fine.
And also there is a new website build in .Net Core but targetting 4.7.2 framework.
The solution I ended up is essentially hosting an OWIN pipeline within the AspCore Pipeline.
First I needed to install the following packages:
Microsoft.Owin
Microsoft.AspNetCore.Owin
I also added a new extension method for the Core IApplicationBuilder interface that sets up OWIN on the same pipeline:
public static class OwinExtensions
{
public static IApplicationBuilder UseOwinApp(this IApplicationBuilder app, Action<IAppBuilder> configuration)
{
return app.UseOwin(setup => setup(next =>
{
IAppBuilder owinApp = new AppBuilder();
var aspNetCoreLifetime = (IApplicationLifetime)app.ApplicationServices.GetService(typeof(IApplicationLifetime));
var owinAppProperties = new AppProperties(owinApp.Properties)
{
OnAppDisposing = aspNetCoreLifetime?.ApplicationStopping ?? CancellationToken.None,
DefaultApp = next
};
configuration(owinApp);
return owinApp.Build<Func<IDictionary<string, object>, Task>>();
}));
}
}
Then in the Startup class of the Core project, in the Configure method I was able to use my extension and register SignalR hubs to it like this:
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseOwinApp(owinApp =>
{
owinApp.MapSignalR();
});
...
}
This way we can add more middlewares to the OWIN pipeline if we need to for whatever reasons.
I hope this helps.

Autofac returns different instance in asp.net mvc web api

I'm using autofac in an asp.net mvc and webapi project.
In the configuration I'm doing this :
var builder = new ContainerBuilder();
builder.Register(x => NHibernateConfigurator.BuildSessionFactory()).SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
Now the problem is that in an api controller if I inject ISession via the constructer and also call
DependencyResolver.Current.GetService<ISession>()
it will return 2 different instances.
I'm guessing the problem is because of these 2 lines :
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
But how can I make it return the same instance ?
Edit:
Just to be more clear - I'm expecting the same instance of ISession per HttpRequest. Right now I'm getting different instances on the same request.
Thanks
Ok, I think I found the answer - it can't be done .. at least not with DependencyResolver.
ASP .Net 4 Web Api RC + Autofac manual resolving
I did what it said in the comments, added IComponentContext to the constructor and used that to resolve what I needed.
It seems to be working. Thanks.