78

I have a simple .net core web api with one action:

[Route("[action]")]
public class APIController : Controller
{
    // GET api/values
    [HttpGet]
    public string Ping()
    {
        return DateTime.Now.ToString();
    }
}

If I run this via dotnet run I get

Hosting environment: Production
Content root path: C:\Users\xxx\Documents\Visual Studio 2015\Projects\SelfHostTest\src\SelfHostTest
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Going to the browser and typing in http://localhost:5000/ping results in a successful return of the current time. However going to a remote machine (same LAN) and trying to access the service via http://odin:5000/ping results in a 404 error. (Odin is the name of the machine running the web api in a console via dotnet run).

Both server (and client!) firewalls are turned off. I can ping "odin" successfully.

Any ideas what simple step I am missing here. I've tried this at home and at work with no success.

Cellcon
  • 1,245
  • 2
  • 11
  • 27
Calanus
  • 25,619
  • 25
  • 85
  • 120
  • What happens if you try with IP address of 'odin'? Ex: 192.111.11.2:5000 ? May be [this](http://stackoverflow.com/questions/12460562/consuming-asp-net-web-api-service-from-other-computer-in-lan) can help you. – Siva Gopal Sep 27 '16 at 19:06
  • same thing tried 192.168.1.2 , both on server and on client. 127.0.0.1 works on the server though! – Calanus Sep 27 '16 at 19:11

8 Answers8

103

My guess is that the issue isn't in your controller, it is in program.cs. You need to modify the construction of your WebHost

var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls("http://localhost:5000", "http://odin:5000", "http://192.168.1.2:5000")
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

Unless you add the UseUrls line, Kestrel isn't going to listen outside of localhost. This makes sense, because in a normal situation Kestrel will be sitting behind a reverse proxy like IIS or NGNIX and doesn't need to bind to external URLs.

Feasoron
  • 3,471
  • 3
  • 23
  • 34
  • 2
    Thanks - this works! Guess this sort of config really needs to be in a config file of some sort though... ? – Calanus Sep 27 '16 at 21:07
  • 3
    Either that or you can use the special ASPNETCORE_URLS environment variable. I wouldn't want to be listening directly with Kestrel in production, though. It really is best to have it sit behind something else. – Feasoron Sep 27 '16 at 21:11
  • 32
    In addition, you can use `.UseUrls("http://*:5000")` instead to accept any incoming requests from port `5000`! – Wingjam Mar 03 '18 at 15:32
  • How would you implement the WebHostBuilder without Startup since with Dotnet 6 there is not Startup. Do you jsut remove the UseStartup method? – Franco Sep 13 '22 at 07:19
  • This does not work for me still. I tried both `UseUrls` and `applicationUrl` in the config from the answer below. My port is explicitly open in the firewall. Still I can only access server from the local machine, including by its local ip (192.168.0.101) – LOST Mar 10 '23 at 18:11
  • I ended up using `netsh portproxy`: `netsh interface portproxy add v4tov4 listenport=5216 127.0.0.1 5216 listenaddress=192.168.0.101 tcp` – LOST Mar 10 '23 at 18:29
  • As mentioned by LOST, remember to add a firewall rule to allow access to port 5000 from the remote machine. – datchung Aug 30 '23 at 19:16
70

The best way is to adjust the launchSettings.json, which is located inside the Properties folder.

Change

"applicationUrl": "https://localhost:5001"

to

"applicationUrl": "https://0.0.0.0:5001"

This allows the Kestrel Web Server to listen for traffic from all Network Interfaces.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 2
    There are two applicationUrl part in asp.net core 3.1 where do I add this part? – Shahriar Rahman Zahin Dec 25 '20 at 23:06
  • 1
    You should add this to whichever profile you are using to launch your application. – Luke May 30 '21 at 09:26
  • 1
    Worked for me! Thanks! Updated `profiles { ProjectName { applicationUrl: "https://0.0.0.0:7036;http://0.0.0.0:5036" } }` in launchSettings.json, and when I started the application, I was prompted by Windows to allow private and public networks. I did, and now I can access it from my phone too. Thanks! – PeterOeClausen Sep 08 '22 at 18:23
  • Jesus, this info was hard to find – BotMaster3000 Nov 22 '22 at 13:53
22

You can simply do the following to create your WebHost, this will allow remote connections to kestrel.

var host = WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://0.0.0.0:80")
                .UseStartup<Startup>()
                .Build();

After using the following code I still wasn't able to access my API remotely, I had to disable the network adapters created by Docker in the windows control panel (Control Panel\Network and Internet\Network Connections)

Alexander Cosman
  • 1,117
  • 11
  • 20
10

In my case (.NET core 2.1) I had to modify the Properties/launchSettings.json file.

Set the applicationUrl to a list of allowed urls separated by semicolons like this

"applicationUrl": "https://localhost:5001;http://odin:5000"

Hope this helps someone out there.

Mendy
  • 7,612
  • 5
  • 28
  • 42
6

For us, it also worked (i don't know if that is a new feature of of core 3.1) it that way:

 public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseKestrel();
                webBuilder.UseIIS();
                webBuilder.UseUrls("http://*:8080");
                webBuilder.UseStartup<Startup>();
            });
Martin Hertig
  • 145
  • 1
  • 10
3

Another way to solve this problem is editing "applicationhost.config" file. in project folder -> .vs (Hidden folder) -> config open "applicationhost.config" file. Under sites section, site name="your project name" in Bindings node add another binding and change localhost with your "IP/Domain" on "bindingInformation", like This:

<site name="project_name" id="2">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
     <virtualDirectory path="/" physicalPath="D:\Projects\project_directory" />
    </application>
    <bindings>
     <binding protocol="http" bindingInformation="*:5000:localhost" />
     <binding protocol="http" bindingInformation="*:5000:192.168.1.2" />
     <binding protocol="http" bindingInformation="*:5000:odin" />
    </bindings>
</site>

remember Visual Studio must be run as Administrator.

Hamed Nikzad
  • 618
  • 8
  • 14
  • Yes "Remember Visual Studio must be run as Administrator." und you wont loose hours in stupidity like me. :) – Mottor Jul 13 '21 at 09:38
1

You can use command line argument

dotnet .\SelfHostTest.dll --urls="http://*:5000/ping"
Alew
  • 316
  • 4
  • 12
0

There is a more accurate way when there are multi IP addresses available on the local machine. Connect a UDP socket and read its local endpoint:

string localIP;
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
    socket.Connect("8.8.8.8", 65530);
    IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
    localIP = endPoint.Address.ToString();
}
FAHID
  • 3,245
  • 3
  • 18
  • 15