Call Microservice from another Microservice in Docker not working - c#

I've two microservices in my dockerized application. One is Web Api Project and second is Web MVC application. I want to call web api in mvc application.
Note: I'm using .Net Core 2.1
I'm making call in this way:
using (var client = new HttpClient())
{
try
{
var res = await
client.GetStringAsync("http://localhost:44398/api/values");
return Ok(res);
}
catch (Exception ex)
{
throw ex;
}
}
But it's giving this error:
An unhandled exception occurred while processing the request.
SocketException: No connection could be made because the target machine
actively refused it
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port,
CancellationToken cancellationToken)
HttpRequestException: No connection could be made because the target
machine actively refused it
WebMVCApp.Controllers.HomeController.Index() in HomeController.cs, line 27
When I making call from browser It's working fine. Even If I use same code without docker and then call the web api from mvc app it working fine.
I also enabled the CORS:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors("CorsPolicy");
app.UseHttpsRedirection();
app.UseMvc();
}
Please help me to solve this issue. I've spend alot of time to fix this but I'm unable to understand what is the issue.
I also read answer from this question on stackoverflow.
Call Microservice from another Microservice within Docker
But I can't understand how I can use just api name as url as explained in this answer. when I use api name in url like this:
https://catalogapi:44398/api/values
It produce this error:
SocketException: No such host is known
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port,
CancellationToken cancellationToken)

Docker compose creates a virtual network on your host, and the services with those IPs are not routable from outside of Docker.
Services can communicate with one another using their names http://running-service/.
We can use a Docker compose file to initialize details such as service name and use it to call the other microservice, for example, http://running-service-1:port/.

Related

Google cloud run unable to connect MQTT

Currently I am developing a .Net6 application with a some controllers and a minimal MQTT Server. So far I have everything working correctly on my local machine, however, when deploying to Google Cloud Run (GCR) I am unable to connect to the MQTT Server.
I noticed that the GCR container wants you to map incoming traffic to a single port (8080 in my case), however I am running MQTT on port 1883 (default) and unable to connect to it. The controllers running on port 8080 are accessible and work fine.
I need some direction toward a solution, preferably in a single container.
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(o =>
{
o.ListenAnyIP(1883, l => l.UseMqtt());
o.ListenAnyIP(8080);
});
...
var app = builder.Build();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints
.MapConnectionHandler<MqttConnectionHandler>("/mqtt",
httpConnectionDispatcherOptions =>
httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector = protocolList => protocolList.FirstOrDefault() ?? string.Empty);
});
app.UseMqttServer(server => server.StartAsync());
app.MapControllers();
app.Run();
A possible option is to not use 2 ports.
If you use MQTT over WebSockets then your broker can share a port with the HTTP server.

gRPC - JsonTranscoding - IOException: Unable to read data from the transport connection

I implemented JsonTranscoding
in my simple gRPC
application. I've a POST
api. When I test my POST
api using swagger, I could call it; but when I test it using Postman or
HttpClient (Acually calling api using code) I get two below exception:
IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
and also:
SocketException: An established connection was aborted by the software in your host machine.
*** I have no firewall on my local machine.**
I figured out that my gRPC service does not support HTTP request and this makes problem. so I cofigured it to support HTTP1 and HTTP2. There is two ways to configure it:
Adding below code in Program.cs :
builder.WebHost.ConfigureKestrel((context, options) =>
{
options.ListenAnyIP(7013, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps();
});
});
or in appsettings.json :
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}

How to host c# grpc service on linux and connect to in using client on windows machine

I have prepared dotnet service using grpc "template" (dotnet new grpc) that does simple CRUD operations on PostgreSQL DB. Service and database are on linux. I want to host it on linux and connect with my client from windows. Both computers are inside the same network - I can ping PC1 from PC2.
I've found that I should add hosting settings to Startup.cs file, but in this template there are no Startup.cs file. I have only Program.cs:
//Program.cs
using client_pgsql;
using client_pgsql.Services;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddGrpc();
builder.Services.AddDbContext<MovieContextClass>(
o=>o.UseNpgsql(builder.Configuration.GetConnectionString("MoviesDB"))
);
var app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
// Configure the HTTP request pipeline.
app.MapGrpcService<MovieService>();
app.MapGet("/movie/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
app.Run();
Could someone tell me what should I do to make this service accessible from another PC? And how to prepare client for this connection.

asp net core 6.0 kestrel server is not working

I have this code running kestrel
builder.WebHost.UseKestrel().UseUrls("https://myfirstproj1.asp")
.UseIISIntegration();
but I can't access the site through the url I specified. What am I doing wrong?
.net 6 does not use UserUrls() method any more.
This is how to do it on .net 6.
On Program.cs
var builder = WebApplication.CreateBuilder(args);
//...
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenAnyIP(5001); // to listen for incoming http connection on port 5001
options.ListenAnyIP(7001, configure => configure.UseHttps()); // to listen for incoming https connection on port 7001
});
//...
var app = builder.Build();
UseKestrel also works for me. No idea what the difference is :/
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(4000);
serverOptions.ListenAnyIP(4001, listenOptions => listenOptions.UseHttps());
});
As of .NET 7 you now need to do this as the above no longer worked for me on .NET 7 projects (although works on .NET 6 projects.
Open appsettings.json and add the following:
{
//Other code above
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5014"
}
}
}
}
You can specify an endpoint for Https here too but I only needed to set an http port as it is proxied from Apache on a Linux server.
Note that if you add an https option here too and do not have a certificate configured then the site will still preview but will fail to load on the Kestrel server on Ubuntu.
It would appear the above option works on .NET 6 too and it seems simpler as enables the URL and port to be set using the settings file in the same way as other configuration options as opposed to changing the code.

How to bind external domain to .NET Core 3.1 Kestrel self-hosted application?

I have a simple .NET Core 3.1 self-hosted Kestrel application. After publishing to my server, it runs correctly at http://localhost:5000.
I want to access this application via a remote browser, so I changed the Program.cs as below:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
{
Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(so =>
{
so.Listen(IPAddress.Any, 5000); //==> This is OK
});
webBuilder.UseStartup<Startup>();
});
}
}
Now the application is reachable from any remote browser via http://IP:port address. Instead of using IP:Port, however, I want to bind a domain URL (for example www.XXXX.com) to my application.
I use Cloudflare as my DNS and proxy server. Keep in mind that Cloudflare does not support port forwarding. Also, the Portzilla App in Cloudflare had no use for me.
What I have done so far is I’ve added a new IP (let’s say 112.250.22.33) to the server, and tried to configure the application to listen on port 80 of this specific IP address:
webBuilder.ConfigureKestrel(so =>
{
so.Listen(IPAddress.Parse("112.250.22.33"), 80); //==> NOT OK
});
With this configuration, however, the application does not run at all—even if I run it in Run as administrator mode. Instead, it returns with this error:
Microsoft.AspNetCore.Server.Kestrel[0]
Unable to start Kestrel.
System.Net.Sockets.SocketException (10013): An attempt was made to access a socket in a way forbidden by its access permissions.
Any help will be appreciated.
I am not sure, but looks like 80 port is holding by IIS. I disabled DefaultWebSite and could bind domain name to local Kestrel run.

Categories

Resources