External Network Access to Kestrel and IIS Express in ASP.NET Core

Today I ported over my AlbumViewer sample Angular 2.0 application I worked on for a workshop for the last few weeks, to my ASP.NET Core project. I’ve been building various different kinds of backends for this Angular 2.0 front end app and it’s been very easy to simply swap them out by changing the base URL to the API endpoints.

I’ve been working on the Angular 2.0 app on my Mac, but the server side ASP.NET I’m moving it to is running on Windows using ASP.NET Core and so I need to run my API application in a Windows VM on Parallels and access this API from the Mac side where the Angular application is running locally using the WebPack dev server.

In order to access the Windows API service from the Mac requires a bit of configuration as by default both Kestrel and IIS Express only serve requests on localhost. Both servers use default bindings that point explicitly at localhost which effectively disables remote access.

In order to make this work there are a couple of configuration steps required:

  • Change the default URL binding to a non-localhost address
  • Open the Firewall port
  • Map a host name to make it easier

Kestrel: What’s the Problem? Url Bindings

The issue is that the default binding that Kestrel uses, binds explicitly to localhost. A localhost bound IP won’t expose to the external network, so even though you might be able to access other ports on the VM over the network – like IIS running on port 80 – accessing of http://<WindowsVmIp>:5000/ is not supported without some configuration changes.

When Kestrel starts without any binding customization you get:

which clearly shows that it’s using the localhost URL.

Override the default URLs

In order to expose Kestrel externally you either have to bind to a specific machine name, IP Address or 0.0.0.0 which stands for all IP Addresses (thanks to @DamianEdwards and @BradyMHolt for their help).

ASP.NET Core allows overriding the startup URLs as part of the startup process for the Web host and there are a number of ways that you can do this:

  • Set the –urls command line parameter
  • Use WebHost.UseUrls()
  • Set up hosting.json

You can override the start this via the launch command line:

 dockerfile
 dotnet run --urls http://0.0.0.0:5001

In order for this to work make sure that command line argument configuration is enabled as part of the startup procedure:

 csharppublic static void Main(string[] args)
 {
  // use this to allow command line parameters in the config
  var configuration = new ConfigurationBuilder()
  .AddCommandLine(args)
  .Build();
  ...
 }

If you want more control you can also explicitly set the host Url or Urls. In code you can use the following – including reading a configuration setting from a custom command line parameter:

 csharppublic static void Main(string[] args)
 {
  // use this to allow command line parameters in the config
  var configuration = new ConfigurationBuilder()
  .AddCommandLine(args)
  .Build();
 ​
 ​
  var hostUrl = configuration["hosturl"];
  if (string.IsNullOrEmpty(hostUrl))
  hostUrl = "http://0.0.0.0:6000";
 ​
 ​
  var host = new WebHostBuilder()
  .UseKestrel()
  .UseUrls(hostUrl) // <!-- this
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseIISIntegration()
  .UseStartup<Startup>()
  .UseConfiguration(configuration)
  .Build();
 ​
  host.Run();
 }

With that in place you could run:

 dockerfiledotnet run                                 // default on port 6000
 dotnet run --hosturl http://0.0.0.0:6001 // explicit

The key is the .UseUrls() call that applies the host url to the Webhost and as you can see you can apply logic and configuration to decide where the value comes from.

Note that you can specify multiple startup URLs separated by semicolons in the string passed.

Open your Firewall

Next you need to make sure that your Windows firewall allows access to the requested port.

 pgsql
 netsh advfirewall firewall add rule name="Http Port 5000" dir=in action=allow protocol=TCP localport=5000

or you can use the interactive Windows Firewall application.

Assuming you used a non-localhost IP address or name, your application should now be externally accessible when you dotnet run.

On the Mac: Create a HOSTS entry

This step is optional, but when developing in a two OS environment I like to make it as easy as possible to identify machines, so I tend to create domain names for the server rather than using an IP address to access it by modifying the HOSTS file on the client machine. So I have dev.west-wind.com locally which maps to the IP address of my Windows virtual machine in Parallels.

With this in place I can now navigate to my app with:

http://dev.west-wind.com:5000/index.html

to get to my ASP.NET Core application on the Windows VM. Schweet!

Exposing IIS Express to the Network

If you want to use IIS Express and allow external access, you need to explicitly change the bindings in the solution applicationhost.config file which can be found in <solutionRoot>\.vs\config. Change the bindingInformation to:

 xml<site name="AlbumViewerNetCore" id="2">
  <application path="/" applicationPool="Clr4IntegratedAppPool">
  <virtualDirectory path="/" physicalPath="C:\projects2010\AlbumViewerVNext\src\AlbumViewerNetCore" />
  </application>
  <bindings>
  <binding protocol="http" bindingInformation="*:26448:*" />
  <binding protocol="https" bindingInformation="*:44319:*" />
  </bindings>
 </site>

changing the *:26448:localhost to *:26448:* where 26448 is the IIS Express port.

Then run:

 nginx
 netsh http add urlacl url=http://*:26448/ user=Interactive listen=yes

to bind the http.sys entry.

Finally open the firewall to allow inbound connections to the specific IIS Express port:

 pgsql
 netsh advfirewall firewall add rule name="Http Port 26448" dir=in action=allow protocol=TCP localport=26448

and you should be off to the races.

daemon.json 옵션 지정하고 부팅 시 서비스가 종료되는 현상

 

Docker는 실행 옵션에 대한 출처가 중복되면 서비스를 시작하지 않고 오류 처리된다. daemon.json, 실행 시 파라미터, /lib/systemd/system/docker.service 파일의 옵션 중 하나만 사용해야 한다.

 기본적으로 docker 설치 시 /lib/systemd/system/docker.service 파일에서 실행 파라미터를 지정했기 때문에 daemon.json 작성 시 오류가 발생한다. 결국 /lib/systemd/system/docker.service 파일의 파라미터 항목을 제거하면 된다.

#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
Code language: PHP (php)

https://github.com/moby/moby/issues/34104#issuecomment-334471105

How do I edit the Visual Studio templates for new C# class/interface?

Extract, edit and recompress. Paths are for the class template, but the interface templates are in the same folder.

You may want to edit the VS template file in each to remove the fact that they don’t automatically add references to the assemblies System, System.Data and/or System.Xml.

2005:

C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE\ItemTemplates\CSharp\1033\Class.zip

2008:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class.zip

2010:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class.zip

Starting with Visual Studio 2012, the templates are not zipped, so you can edit each .cs template in each applicable folder directly.

2012:

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class\Class.cs

2013:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class\Class.cs

2015:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class\Class.cs

2017

VS 2017 changes the directory location, and is now dependent on your edition (Professional/Enterprise/etc). So for the Enterprise edition:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class\Class.cs

2019

The VS 2019 location is similar to 2017. So for the Enterprise edition:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\ItemTemplates\CSharp\Code\1033\Class\Class.cs

Notes

Express Editions

In Express Editions you will have to search in the subdirectory WDExpress inside the IDE folder, so e.g. for VS 2015 Express:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WDExpress\ItemTemplates\CSharp\Code\1033\Class\Class.cs

Other Languages

If you don’t use the English version of Visual Studio, the folder 1033 may not exist, but a different number representing your language. For example it is 1031 in a German installation.

윈도우10 내 PC 라이브러리 폴더 삭제

정확히 이번에 삭제하려는 것은 내 PC를 눌렀을 때 나오는 폴더들(문서, 다운로드, 동영상, 사진, 바탕화면 등)입니다. 이 폴더들을 삭제해서 앞으로 내 PC를 누르면 깔끔하게 장치 및 드라이브만 나오게 할 예정이죠.

위 이미지를 참고하시면 정확히 어떤걸 삭제하려고 하는지 알 수 있으실 겁니다. 윈도우 탐색기를 눌러서 내 PC를 눌렀을 때 보이는 폴더들이죠.

이 글에서는 제거 방법 2가지를 제시합니다. 하나는 직접 레지스트리를 열어서 삭제하는 방법, 다른 하나는 제가 첨부하는 파일을 다운받아 제거하는 방법입니다. 둘 다 원리는 똑같기 때문에 개인적으로 첨부파일로 제거하는 것을 추천합니다.

  1. 파일을 통해 제거하기

내 PC 라이브러리 폴더 제거 파일
혹시나 제거한 파일을 복원하려면 ‘윈도우10 라이브러리 복원’ 파일을 이용해서 복원하시면 됩니다.

사용 방법
‘윈도우10 라이브러리 제거.reg’ 파일을 우클릭하여 병합을 하면 됩니다. 만약에 일부 폴더만 삭제하고 싶다면 우클릭하여 편집을 누른 뒤, 주석을 보고 살려둘 폴더를 삭제하면 그 부분은 제거되지 않습니다.

  1. 레지스트리에서 직접 제거
    위의 파일을 통해 삭제하는 것이 불안하신 분들은 레지스트리로 직접 이동하여 삭제하시면 됩니다. 방식은 똑같기 때문에 개인적으로는 파일을 통해 제거하는 것을 추천합니다.

레지스트리 실행 후 아래 경로로 이동
Win+R키를 입력하여 실행을 불러온 뒤 ‘regedit’을 입력하여 편집기를 불러온 뒤 아래 경로로 이동
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\

삭제하고 싶은 폴더의 값을 선택 제거
※ 다른 키들을 함부로 삭제하면 윈도우가 맛이 갈 수도 있으니 해당 값만 제거해주세요.

다운로드 : {088e3905-0323-4b02-9826-5d99428e115f}
사진 : {24ad3ad4-a569-4530-98e1-ab02f9417aa8}
음악 : {3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}
문서 : {d3162b92-9365-467a-956b-92703aca08af}
동영상 : {f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}
바탕화면 : {B4BFCC3A-DB2C-424C-B029-7FE99A87C641}
3D개체 : {0DB7E03F-FC29-4DC6-9020-FF41B59E513A}