Good morning,
I am porting from .NET Framework 4.8 to .NET Core 8.0. I have not changed the code, I have only used different libraries.
I start the server without errors, but it does not listen on the ports I specify in Start().
What am I doing wrong? Do I need to adapt the code for .NET Core?
I notice that in all project templates, the service is started using WebApplication.CreateBuilder(). In the mode I am starting from (version for .NET Framework), I did not use that method.
Has it become necessary, or can I continue to use new AppHost().Init().Start(listeningUrls)?
Thank you, but I was referring to the fact that a web application is always created in the templates. I need to have a Windows service. Is there a way to use it as a Windows service (like an HttpListener, so to speak) and not as a web application?
To see if I understand correctly. In .NET Framework, I could do new AppHost().Init().Start(listeningUrls) and start a server listening on the specified ports. Now, with .NET Core 8, I can no longer do that and must follow the example of the Background MQ Workers template?
I am integrating the ‘Single project’ template into my application. Is there a way to set the listening ports programmatically and in the format ‘http://+8080’ instead of using the launchSettings.json file?
I downloaded the RabbitMQ template, and as soon as I launch it, I get this error:
ServiceStack.RabbitMq.RabbitMqServer[0]
Exception in Rabbit MQ Server: None of the specified endpoints were reachable
RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were reachable
---> System.AggregateException: One or more errors occurred. (Connection failed)
---> RabbitMQ.Client.Exceptions.ConnectFailureException: Connection failed
---> System.Net.Sockets.SocketException (11001): Host sconosciuto.
at System.Net.NameResolutionPal.ProcessResult(SocketError errorCode, GetAddrInfoExContext* context)
at System.Net.NameResolutionPal.GetAddressInfoExCallback(Int32 error, Int32 bytes, NativeOverlapped* overlapped)
--- End of stack trace from previous location ---
at System.Net.Dns.<GetAddrInfoWithTelemetryAsync>g__CompleteAsync|35_0[T](Task task, String hostName, Int64 startingTimeStamp)
at RabbitMQ.Client.TcpClientAdapter.ConnectAsync(String host, Int32 port)
at RabbitMQ.Client.Impl.TaskExtensions.TimeoutAfter(Task task, TimeSpan timeout)
at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail(ITcpClient socket, AmqpTcpEndpoint endpoint, TimeSpan timeout)
--- End of inner exception stack trace ---
at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail(ITcpClient socket, AmqpTcpEndpoint endpoint, TimeSpan timeout)
at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectUsingAddressFamily(AmqpTcpEndpoint endpoint, Func`2 socketFactory, TimeSpan timeout, AddressFamily family)
at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectUsingIPv4(AmqpTcpEndpoint endpoint, Func`2 socketFactory, TimeSpan timeout)
at RabbitMQ.Client.Impl.SocketFrameHandler..ctor(AmqpTcpEndpoint endpoint, Func`2 socketFactory, TimeSpan connectionTimeout, TimeSpan readTimeout, TimeSpan writeTimeout)
at RabbitMQ.Client.Framing.Impl.IProtocolExtensions.CreateFrameHandler(IProtocol protocol, AmqpTcpEndpoint endpoint, ArrayPool`1 pool, Func`2 socketFactory, TimeSpan connectionTimeout, TimeSpan readTimeout, TimeSpan writeTimeout)
at RabbitMQ.Client.ConnectionFactory.CreateFrameHandler(AmqpTcpEndpoint endpoint)
at RabbitMQ.Client.EndpointResolverExtensions.SelectOne[T](IEndpointResolver resolver, Func`2 selector)
--- End of inner exception stack trace ---
at RabbitMQ.Client.EndpointResolverExtensions.SelectOne[T](IEndpointResolver resolver, Func`2 selector)
at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(IEndpointResolver endpoints)
at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver, String clientProvidedName)
--- End of inner exception stack trace ---
at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver, String clientProvidedName)
at RabbitMQ.Client.ConnectionFactory.CreateConnection(String clientProvidedName)
at RabbitMQ.Client.ConnectionFactory.CreateConnection()
at ServiceStack.RabbitMq.RabbitMqServer.get_Connection() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.RabbitMq/RabbitMqServer.cs:line 144
at ServiceStack.RabbitMq.RabbitMqServer.Init() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.RabbitMq/RabbitMqServer.cs:line 267
at ServiceStack.RabbitMq.RabbitMqServer.Start() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.RabbitMq/RabbitMqServer.cs:line 339
Using your templates and following your advice, I’ve managed to start an AppHostBase server that exposes my responses.
I do have one question, though: should the JsonServiceClient I was using before still work now?
I’m asking because I’m having trouble retrieving the public key.
using (JsonServiceClient jsonServiceClient = new JsonServiceClient($"http://{IpAddress}:{PortHttp}/"))
{
var publicKey = jsonServiceClient.Get(new GetPublicKey());
....
}
Is there another way to obtain the public key needed to instantiate an IEncryptedClient?
class MyService(JsonApiClient client)
{
public async Task<object>(MyRequest requset)
{
var api = await client.ApiAsync(new GetPublicKey());
var key = api.Response;
}
}
You should use Api and ApiAsync so it uses the primary HTTP Method.
You can’t use Plugins.Add anymore, plugins need to be registered before the App and AppHost is created with services.AddPlugin, e.g:
public class AppHost() : AppHostBase("MyApp"), IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices(services => {
// Configure ASP.NET Core IOC Dependencies
services.AddPlugin(...);
});
}
Unfortunately, for backward compatibility reasons, I have to use JsonServiceClient here. I know it would be better to use JsonApiClient. If necessary, I could write some custom code.
This is how I implemented your suggestion above:
private class MyService
{
private readonly JsonServiceClient _client;
public MyService(JsonServiceClient client)
{
_client = client;
}
public async Task<GetCertificateResponse> GetCertificate(GetCertificateRequest request)
{
var api = await _client.ApiAsync(new GetPublicKey());
var publicKey = api.Response;
IEncryptedClient encryptedClient = _client.GetEncryptedClient(publicKey);
var response = encryptedClient.Post(new GetCertificateRequest());
return response;
}
}
Used as follows:
using (JsonServiceClient jsonServiceClient = new JsonServiceClient($"https://{IpAddress}:{PortHttp}/"))
{
MyService myService = new MyService(jsonServiceClient);
var certificate = myService.GetCertificate(new GetCertificateRequest()).Result;
....
If I ask you to try something, please don’t ignore it and then just say you’re getting the same error. If you’re not going to try it, I need to know exactly what you’re trying instead. Please don’t let me believe you’re getting the same error but are not trying what I’ve said.
The only efficient way to use a HttpClient is with the IOC, using JsonServiceClient uses WebServiceClient which is deprecated and an inefficient wrapper over HttpClient. You also shouldn’t use .Result; which is sync over async.
By showing dependency injection:
class MyService(JsonApiClient client)
{
}
I mean that you need to use dependency injection to resolve the JsonApiClient instance, and not to dispose it since the life cycle is handled by the IOC.
Note both JsonApiClient and JsonServiceClient implements the same IServiceClient so you could use that, otherwise pass the public key string in instead.
Now can you let me know if a Service that uses AddJsonApiClient and JsonApiClient works?
public class GetKey : IGet, IReturn<string> {}
class MyService(JsonApiClient client) : Service
{
public async Task<object> Any(GetKey request)
{
var api = await client.ApiAsync(new GetPublicKey());
return api.Response;
}
}