Visual Studio and IIS Error: Specified argument was out of the range of valid values. Parameter name: site

I got a very obscure and obtuse error running an ASP.NET application under Visual Studio and IIS Express recently. I’m running a Windows 10 Insiders (Fast Ring) build, so it’s likely an issue with that, but since I was able to resolve the issue simply, I figured I’d blog it for google posterity .

I would run the ASP.NET app from within Visual Studio and get this totally useless error. It was happening VERY early in the bootstrapping process and NOT in my application. It pretty clearly is happening somewhere in the depths of IIS Express, perhaps in a configurator in HttpRuntime.

Specified argument was out of the range of valid values.
Parameter name: site

I fixed it by going to Windows Features and installing “IIS Hostable Web Core,” part of Internet Information Services. I did this in an attempt to “fix whatever’s wrong with IIS Express.”

Turn Windows Features on or off

That seems to “repair” IIS Express. I’ll update this post if I learn more, but hopefully if you got to this post, this fixed it for you also.


Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test, build and debug ASP.NET, .NET Framework, .NET Core, or Unity applications. Learn more and get access to early builds!


© 2017 Scott Hanselman. All rights reserved.
     

I got a very obscure and obtuse error running an ASP.NET application under Visual Studio and IIS Express recently. I'm running a Windows 10 Insiders (Fast Ring) build, so it's likely an issue with that, but since I was able to resolve the issue simply, I figured I'd blog it for google posterity .

I would run the ASP.NET app from within Visual Studio and get this totally useless error. It was happening VERY early in the bootstrapping process and NOT in my application. It pretty clearly is happening somewhere in the depths of IIS Express, perhaps in a configurator in HttpRuntime.

Specified argument was out of the range of valid values.
Parameter name: site

I fixed it by going to Windows Features and installing "IIS Hostable Web Core," part of Internet Information Services. I did this in an attempt to "fix whatever's wrong with IIS Express."

Turn Windows Features on or off

That seems to "repair" IIS Express. I'll update this post if I learn more, but hopefully if you got to this post, this fixed it for you also.


Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test, build and debug ASP.NET, .NET Framework, .NET Core, or Unity applications. Learn more and get access to early builds!


© 2017 Scott Hanselman. All rights reserved.
     

How to enable HTTP Strict Transport Security (HSTS) in IIS7+

I got a report of a strange redirect loop on a website I (inherited, but help) manage. The reports were only from Chrome and Firefox users and just started suddenly last week, but the code on this site hadn’t changed in at least 3 years, maybe longer.

Chrome shows an error "this webpage has a redirect loop"

What’s going on here? Well, it’s a redirect loop, LOL. But what KIND of redirects?

We know about these redirects, right?

  • 302 – Object Moved – Look over here at THIS URL!
  • 301 – Moved Permanently – NEVER COME HERE AGAIN. Go over to THIS URL!

A redirect loop builds up in the Chrome Developer Tools

But there’s another kind of redirect.

  • 307 – Internal Redirect – Someone told me earlier to go over HERE so I’m going to go there without talking to the server. Imma redirect myself.

A 307 Internal Redirect

Note the reason for the 307! HSTS. What’s that?

HSTS: Strict Transport Security

HSTS is a way to keep you from inadvertently switching AWAY from SSL once you’ve visited a site via HTTPS. For example, you’d hate to go to your bank via HTTPS, confirm that you’re secure and go about your business only to notice that at some point you’re on an insecure HTTP URL. How did THAT happen, you’d ask yourself.

But didn’t we write a bunch of code back in the day to force HTTPS?

Sure, but this still required that we ask the server where to go at least once, over HTTP…and every subsequent time, user keeps going to an insecure page and then redirecting.

HSTS is a way of saying “seriously, stay on HTTPS for this amount of time (like weeks). If anyone says otherwise, do an Internal Redirect and be secure anyway.”

Some websites and blogs say that to implement this in IIS7+ you should just add the CustomHeader require for HSTS like this in your web.config. This is NOT correct:

<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000"/>
</customHeaders>
</httpProtocol>
</system.webServer>

This isn’t technically to spec. The problem here is that you’re sending the header ALWAYS even when you’re not under HTTPS.

The HSTS (RFC6797) spec says

An HTTP host declares itself an HSTS Host by issuing to UAs (User Agents) an HSTS Policy, which is represented by and conveyed via the
Strict-Transport-Security HTTP response header field over secure transport (e.g., TLS).

You shouldn’t send Strict-Transport-Security over HTTP, just HTTPS. Send it when they can trust you.

Instead, redirect folks to a secure version of your canonical URL, then send Strict-Transport-Security. Here is a great answer on StackOverflow from Doug Wilson.

Note the first rule directs to a secure location from insecure one. The second one adds the HTTP header for Strict-Transport-Security. The only thing I might change would be to formally canonicalize the www. prefix versus a naked domain.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}"
redirectType="Permanent" />
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security"
pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>

Note also that HTTP Strict Transport Security is coming to IE and Microsoft Edge as well, so it’s an important piece of technology to understand.

What was happening with my old (inherited) website? Well, someone years ago wanted to make sure a specific endpoint/page on the site was served under HTTPS, so they wrote some code to do just that. No problem, right? Turns out they also added an else that effectively forced everyone to HTTP, rather than just using the current/inherited protocol.

This was a problem when Strict-Transport-Security was turned on at the root level for the entire domain. Now folks would show up on the site and get this interaction:

  • GET http://foo/web
  • 301 to http://foo/web/ (canonical ending slash)
  • 307 to https://foo/web/
  • 301 to http://foo/web (internal else that was dumb and legacy)
  • rinse, repeat

What’s the lesson here? A configuration change that turned this feature on at the domain level of course affected all sub-directories and apps, including our legacy one. Our legacy app wasn’t ready.

Be sure to implement HTTP Strict Transport Security (HSTS) on all your sites, but be sure to test and KNOW YOUR REDIRECTS.

Related Links


© 2015 Scott Hanselman. All rights reserved.
     

I got a report of a strange redirect loop on a website I (inherited, but help) manage. The reports were only from Chrome and Firefox users and just started suddenly last week, but the code on this site hadn't changed in at least 3 years, maybe longer.

Chrome shows an error "this webpage has a redirect loop"

What's going on here? Well, it's a redirect loop, LOL. But what KIND of redirects?

We know about these redirects, right?

  • 302 - Object Moved - Look over here at THIS URL!
  • 301 - Moved Permanently - NEVER COME HERE AGAIN. Go over to THIS URL!

A redirect loop builds up in the Chrome Developer Tools

But there's another kind of redirect.

  • 307 - Internal Redirect - Someone told me earlier to go over HERE so I'm going to go there without talking to the server. Imma redirect myself.

A 307 Internal Redirect

Note the reason for the 307! HSTS. What's that?

HSTS: Strict Transport Security

HSTS is a way to keep you from inadvertently switching AWAY from SSL once you've visited a site via HTTPS. For example, you'd hate to go to your bank via HTTPS, confirm that you're secure and go about your business only to notice that at some point you're on an insecure HTTP URL. How did THAT happen, you'd ask yourself.

But didn't we write a bunch of code back in the day to force HTTPS?

Sure, but this still required that we ask the server where to go at least once, over HTTP...and every subsequent time, user keeps going to an insecure page and then redirecting.

HSTS is a way of saying "seriously, stay on HTTPS for this amount of time (like weeks). If anyone says otherwise, do an Internal Redirect and be secure anyway."

Some websites and blogs say that to implement this in IIS7+ you should just add the CustomHeader require for HSTS like this in your web.config. This is NOT correct:

<system.webServer>

<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000"/>
</customHeaders>
</httpProtocol>
</system.webServer>

This isn't technically to spec. The problem here is that you're sending the header ALWAYS even when you're not under HTTPS.

The HSTS (RFC6797) spec says

An HTTP host declares itself an HSTS Host by issuing to UAs (User Agents) an HSTS Policy, which is represented by and conveyed via the

Strict-Transport-Security HTTP response header field over secure transport (e.g., TLS).

You shouldn't send Strict-Transport-Security over HTTP, just HTTPS. Send it when they can trust you.

Instead, redirect folks to a secure version of your canonical URL, then send Strict-Transport-Security. Here is a great answer on StackOverflow from Doug Wilson.

Note the first rule directs to a secure location from insecure one. The second one adds the HTTP header for Strict-Transport-Security. The only thing I might change would be to formally canonicalize the www. prefix versus a naked domain.

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}"
redirectType="Permanent" />
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security"
pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>

Note also that HTTP Strict Transport Security is coming to IE and Microsoft Edge as well, so it's an important piece of technology to understand.

What was happening with my old (inherited) website? Well, someone years ago wanted to make sure a specific endpoint/page on the site was served under HTTPS, so they wrote some code to do just that. No problem, right? Turns out they also added an else that effectively forced everyone to HTTP, rather than just using the current/inherited protocol.

This was a problem when Strict-Transport-Security was turned on at the root level for the entire domain. Now folks would show up on the site and get this interaction:

  • GET http://foo/web
  • 301 to http://foo/web/ (canonical ending slash)
  • 307 to https://foo/web/
  • 301 to http://foo/web (internal else that was dumb and legacy)
  • rinse, repeat

What's the lesson here? A configuration change that turned this feature on at the domain level of course affected all sub-directories and apps, including our legacy one. Our legacy app wasn't ready.

Be sure to implement HTTP Strict Transport Security (HSTS) on all your sites, but be sure to test and KNOW YOUR REDIRECTS.

Related Links



© 2015 Scott Hanselman. All rights reserved.
     

Announcing: Running Ruby on Rails on IIS8 (or anything else, really) with the new HttpPlatformHandler

For years there’s been numerous hacks and ways to get Ruby on Rails to run on IIS. There’s also ways to get Java via Tomcat or Jetty, Go, and other languages and environments to run as well. There’s ways to get Node.JS running on IIS using iisnode but that’s been node-specific. The blog posts you do find say things like “get Rails to run on IIS in 10 steps” and I’m like JUST TEN?!? Why not 13? Others say “You can deploy Rails under IIS, it’s just very difficult and there’s not a lot of documentation. You’ll need a special Fast-CGI implementation…WELCOME TO HELL.”

No longer.

Azure Websites has supported node AND Java (again, Tomcat or Jetty) for a while now, in production and it’s very nice and it runs under IIS. How? They’ve now brought that support to Windows running IIS 8+ with the release of the HttpPlatformHandler. Here’s their example on how to get IIS 8+ running Java, easily.

Let’s see if this works well with Ruby on Rails as well!

Why is HttpPlatformHandler interesting? Check this from the docs…it means IIS can host anything that runs on Windows now, easily. These things were possible before, but with all kinds of hacks and FastCGI this and that. What’s great about HttpPlatformHandler is that it isn’t about Rails. It’s about any process that’s listening on a port. You get all the value of IIS *and* total control of your self-hosting scenario.

The HttpPlatformHandler is an IIS Module, for IIS 8+, which does the following two things:

  1. Process management of http listeners – this could be any process that can listen on a port for http requests.  For example – Tomcat, Jetty, Node.exe, Ruby etc;
  2. Proxy requests to the process that it manages.

To be clear, you can work with Ruby on Rails on Windows and have it host itself with WEBrick locally, but if you’re going to go production on Windows you’ll want to have IIS. What value does IIS provide in a scenario like this? Static file hosting, Reverse Proxy, complex auth that can span multiple apps, languages and frameworks, it monitors and manages your process looking at memory and CPU, crashes, etc.

Running Ruby on Rails on IIS 8 with the HttpPlatformHandler

First make sure you have Ruby on Rails. If you do, skip forward.

I use the http://railsinstaller.org for Windows and go. You’ll get Ruby, Rails, Bundler, Sqlite, and TinyTDS. Even SQL Server support. Very kind of them. Another good Rails on Windows on is RailsFTW.

I go to Turn Windows Features On and Off to make sure I have IIS installed as well.

image

Then get the HttpPlatformHandler. You can get it with the Web Platform Installer, or just install it from here: x86/x64

I make a folder for the app I’m going to make. I put it in c:inetpubwwwrootrails but you can move it around if you like.

Rails in IIS

I right-click my folder in IIS Manager and “Convert to Application.”

My Rails application in IIS

I run “gem install rails” to make sure I have Rails in the first place. 😉 You will if you installed with the RailsInstaller. If you installed with the RubyInstaller, then this will get you Rails.

NOTE: If you have issues with SSL running gem on Windows, you’ll need manually to update gem to 2.2.3 as of the time of this writing. I’m not sure why this isn’t already done by the installer. The symptom I saw was weird errors on ‘bundle install’ that was fixed by this.

image

Then, from inside c:inetpubwwwrootrails, I ran “rails new helloworld.” I ended up moving this folder up. I should have just made the app first, then converted the folder to an app in IIS. Order of operations and all that, eh?

OK, now I’ll “rails server” from within c:inetpubwwwrootrails, just to make sure Rails can run under the local WEBrick server. And it does:

image

Now, let’s do it under IIS.

I need to make sure there’s a web.config file in the same root folder as my Rails app. WHAT?!? Web.config is for ASP.NET, right? Well, no. It’s config for any IIS application. You’ll need this for Go, Java, PHP, Rails, node, ASP.NET, whatever. IIS can host basically anything.

Lemme add a hello world controller and edit its view. I’ll “rails generate controller welcome index” then edit appviewswelcomeindex.html.erb for good measure.

I put my Rails app under http://localhost/rails rather than at the root http://localhost so I did need to tell Rails 4 about the fact it’s running in a subdirectory with a change to /config.ru, otherwise my routes wouldn’t line up.

Rails.application.config.relative_url_root = '/rails' map Rails.application.config.relative_url_root || "/" do   run Rails.application end

Make special note of the paths below AND the encoded &quot; there in the arguments. That’s important, because it’s a quoted argument passed into the ruby.exe process that IIS will kick off. Note also the %HTTP_PLATFORM_PORT% environment variable reference. That is passed in by IIS and will be a localhost-bound high port.

I also put in foo and bar for theoretical environment variables you might want your Rails app to know about. For example, I might add:

<environmentVariable name="RAILS_ENV" value="production"/>

…when it’s time. I put in some standard debug logging there with the “stdout” but you can remove that if you don’t want the clutter. Make sure your IISR_ users have write access to the folders if you want to see any logs.

Also, on slower machines when running in development, you might need to up your startupTimeLimit if you are seeing IIS stop your Ruby processes that take to long to startup.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
</handlers>
<httpPlatform stdoutLogEnabled="true" stdoutLogFile="rails.log" startupTimeLimit="20" processPath="c:RailsInstallerRuby2.1.0binruby.exe"
arguments="&quot;C:RailsInstallerRuby2.1.0binrails&quot; server -p %HTTP_PLATFORM_PORT% -b 127.0.0.1">
<environmentVariables>
<environmentVariable name="foo" value="bar"/>
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>

Here’s a screenshot of Ruby within the SysInternals Process Explorer application. I wanted to show you this so you could see the Process Tree and see who started which process. You can see w3wp (that’s IIS) which is a Service, and it’s hosting Ruby, running Rails. Make note of the command line arguments as well.

image

And here it is. Ruby on Rails 4 running under IIS8 on my Windows 8 machine.

Ruby on Rails on IIS on Windows

Big thanks to Ranjith Ramachandra (@ranjithtweets) at Microsoft for the help with the web.config values!

TL;DR

So, basically, to give you the TL;DR version, except at the end. When you have IIS, install HttpPlatformHandler and add a web.config as appropriate and you’re all set. Run what you like, passing in the port that IIS will proxy to.

Related Links


Sponsor: Big thanks to Infragistics for sponsoring the feed this week! Responsive web design on any browser, any platform and any device with Infragistics jQuery/HTML5 Controls.  Get super-charged performance with the world’s fastest HTML5 Grid – Download for free now!


© 2014 Scott Hanselman. All rights reserved.
     

For years there's been numerous hacks and ways to get Ruby on Rails to run on IIS. There's also ways to get Java via Tomcat or Jetty, Go, and other languages and environments to run as well. There's ways to get Node.JS running on IIS using iisnode but that's been node-specific. The blog posts you do find say things like "get Rails to run on IIS in 10 steps" and I'm like JUST TEN?!? Why not 13? Others say "You can deploy Rails under IIS, it's just very difficult and there's not a lot of documentation. You'll need a special Fast-CGI implementation...WELCOME TO HELL."

No longer.

Azure Websites has supported node AND Java (again, Tomcat or Jetty) for a while now, in production and it's very nice and it runs under IIS. How? They've now brought that support to Windows running IIS 8+ with the release of the HttpPlatformHandler. Here's their example on how to get IIS 8+ running Java, easily.

Let's see if this works well with Ruby on Rails as well!

Why is HttpPlatformHandler interesting? Check this from the docs...it means IIS can host anything that runs on Windows now, easily. These things were possible before, but with all kinds of hacks and FastCGI this and that. What's great about HttpPlatformHandler is that it isn't about Rails. It's about any process that's listening on a port. You get all the value of IIS *and* total control of your self-hosting scenario.

The HttpPlatformHandler is an IIS Module, for IIS 8+, which does the following two things:

  1. Process management of http listeners - this could be any process that can listen on a port for http requests.  For example - Tomcat, Jetty, Node.exe, Ruby etc;
  2. Proxy requests to the process that it manages.

To be clear, you can work with Ruby on Rails on Windows and have it host itself with WEBrick locally, but if you're going to go production on Windows you'll want to have IIS. What value does IIS provide in a scenario like this? Static file hosting, Reverse Proxy, complex auth that can span multiple apps, languages and frameworks, it monitors and manages your process looking at memory and CPU, crashes, etc.

Running Ruby on Rails on IIS 8 with the HttpPlatformHandler

First make sure you have Ruby on Rails. If you do, skip forward.

I use the http://railsinstaller.org for Windows and go. You'll get Ruby, Rails, Bundler, Sqlite, and TinyTDS. Even SQL Server support. Very kind of them. Another good Rails on Windows on is RailsFTW.

I go to Turn Windows Features On and Off to make sure I have IIS installed as well.

image

Then get the HttpPlatformHandler. You can get it with the Web Platform Installer, or just install it from here: x86/x64

I make a folder for the app I'm going to make. I put it in c:inetpubwwwrootrails but you can move it around if you like.

Rails in IIS

I right-click my folder in IIS Manager and "Convert to Application."

My Rails application in IIS

I run "gem install rails" to make sure I have Rails in the first place. ;) You will if you installed with the RailsInstaller. If you installed with the RubyInstaller, then this will get you Rails.

NOTE: If you have issues with SSL running gem on Windows, you'll need manually to update gem to 2.2.3 as of the time of this writing. I'm not sure why this isn't already done by the installer. The symptom I saw was weird errors on 'bundle install' that was fixed by this.

image

Then, from inside c:inetpubwwwrootrails, I ran "rails new helloworld." I ended up moving this folder up. I should have just made the app first, then converted the folder to an app in IIS. Order of operations and all that, eh?

OK, now I'll "rails server" from within c:inetpubwwwrootrails, just to make sure Rails can run under the local WEBrick server. And it does:

image

Now, let's do it under IIS.

I need to make sure there's a web.config file in the same root folder as my Rails app. WHAT?!? Web.config is for ASP.NET, right? Well, no. It's config for any IIS application. You'll need this for Go, Java, PHP, Rails, node, ASP.NET, whatever. IIS can host basically anything.

Lemme add a hello world controller and edit its view. I'll "rails generate controller welcome index" then edit appviewswelcomeindex.html.erb for good measure.

I put my Rails app under http://localhost/rails rather than at the root http://localhost so I did need to tell Rails 4 about the fact it's running in a subdirectory with a change to /config.ru, otherwise my routes wouldn't line up.

Rails.application.config.relative_url_root = '/rails' map Rails.application.config.relative_url_root || "/" do   run Rails.application end

Make special note of the paths below AND the encoded &quot; there in the arguments. That's important, because it's a quoted argument passed into the ruby.exe process that IIS will kick off. Note also the %HTTP_PLATFORM_PORT% environment variable reference. That is passed in by IIS and will be a localhost-bound high port.

I also put in foo and bar for theoretical environment variables you might want your Rails app to know about. For example, I might add:

<environmentVariable name="RAILS_ENV" value="production"/>

...when it's time. I put in some standard debug logging there with the "stdout" but you can remove that if you don't want the clutter. Make sure your IISR_ users have write access to the folders if you want to see any logs.

Also, on slower machines when running in development, you might need to up your startupTimeLimit if you are seeing IIS stop your Ruby processes that take to long to startup.

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
<system.webServer>
<handlers>
<add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
</handlers>
<httpPlatform stdoutLogEnabled="true" stdoutLogFile="rails.log" startupTimeLimit="20" processPath="c:RailsInstallerRuby2.1.0binruby.exe"
arguments="&quot;C:RailsInstallerRuby2.1.0binrails&quot; server -p %HTTP_PLATFORM_PORT% -b 127.0.0.1">
<environmentVariables>
<environmentVariable name="foo" value="bar"/>
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>

Here's a screenshot of Ruby within the SysInternals Process Explorer application. I wanted to show you this so you could see the Process Tree and see who started which process. You can see w3wp (that's IIS) which is a Service, and it's hosting Ruby, running Rails. Make note of the command line arguments as well.

image

And here it is. Ruby on Rails 4 running under IIS8 on my Windows 8 machine.

Ruby on Rails on IIS on Windows

Big thanks to Ranjith Ramachandra (@ranjithtweets) at Microsoft for the help with the web.config values!

TL;DR

So, basically, to give you the TL;DR version, except at the end. When you have IIS, install HttpPlatformHandler and add a web.config as appropriate and you're all set. Run what you like, passing in the port that IIS will proxy to.

Related Links


Sponsor: Big thanks to Infragistics for sponsoring the feed this week! Responsive web design on any browser, any platform and any device with Infragistics jQuery/HTML5 Controls.  Get super-charged performance with the world’s fastest HTML5 Grid – Download for free now!



© 2014 Scott Hanselman. All rights reserved.