Scott Hanselman

Working with SSL at Development Time is easier with IISExpress

April 22, 2011 Comment on this post [40] Posted in ASP.NET | ASP.NET MVC | IIS | VS2010
Sponsored By

The Video of my Mix TalkOne of the demos in my Mix 11 talk "An Overview of the MS Web Stack of Love" was showing how IIS Express and Visual Studio SP1 (as well as WebMatrix) can make working with SSL (Secure Sockets Layer) a heck of a lot easier.

If you've used Cassini before (that's the little built in Visual Web Developer Server) you've likely noticed that I doesn't support SSL. This makes working with real world sites a little challenging. If you want your Login pages and Account Management pages to use secure sockets, you'd typically have to do all your work with the full version of IIS, either installed on your own machine or using a shared server.

Here's a few ways to enable SSL. The first is new in Visual Studio 2010 SP1 and will allow you to use SSL on local host over ports 44300 and higher. This means you'll be able to test and develop how your site will work over SSL, but not over port 443 proper. I'll show you that in the final step.

If you watch the Mix video, you'll see towards the end where Damian Edwards educates me on this new SSL feature in VS2010SP1. I didn't know that VS2010SP1 (WebMatrix does also) installs some self-signed certificates and includes and option for turning on their use. However, as I pointed out in the video, that's only for high "strange" ports like 44300+, so my more complex example still has value if you want standard port numbers.

The Easy Way - Local SSL with IIS Express and VS2010 or WebMatrix

If you have IIS Express and VS2010SP1, you can do this now and follow along. Make a new ASP.NET Site in Visual Studio.

Right click on the Project in Solution and select Use IIS Express. You can also set IIS Express as the default from the Tools | Options | Projects and Solutions | Web Projects.

The "Use IIS Express" option in Visual Studio

Next, click Yes, and VS will "make a new site" on IIS Express. What does that mean?

Create a new IIS Web Site?

Click yes and let's find out.

Remember that IIS Express is really IIS. It's just "local personal not-a-service" IIS. That means that IISExpress puts its config files in C:\Users\YOU\Documents\IISExpress\config rather than in some machine-wide location.

My project is called "MvcApplication18" so I can open up my ApplicationHost.config and look for "MvcApplication18." You can too. There's my site, right there, in IISExpress's applicationHost.config:

<site name="MvcApplication18" id="39">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="c:\users\scottha\documents\visual studio 2010\Projects\MvcApplication18\MvcApplication18" />
<binding protocol="http" bindingInformation="*:15408:localhost" />

Note the binding section. I can see that my site will show up on http://localhost:15408.

Go back to Visual Studio, click on your project and press F4 to bring up the properties dialog. You can also press Ctrl-W, then P, or select View | Property Window.

Since I'm using IIS Express and I have VS2010 SP1 installed, I have a new option, "SSL Enabled." If I click it, a new "SSL URL" shows up with a new port number chosen from that pool of ports I mentioned before.

Look at that! It's an option for SSL Enabled = True. Crazy.

Go back over to your ApplicationHost.config if you want to see what really happened.

<site name="MvcApplication18" id="39">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="c:\users\scottha\documents\visual studio 2010\Projects\MvcApplication18\MvcApplication18" />
<binding protocol="http" bindingInformation="*:15408:localhost" />
<binding protocol="https" bindingInformation="*:44302:localhost" />

See that new binding? That was created for us when we clicked SSL Enabled = True.

Run your site. Visit it with and without SSL. Don't forget the port number! You're now running under SSL locally, but you're reminded you are a bad person because this certificate is not trusted. Still, create an app, check a box and you've got local SSL.

You are a bad person, says IE9. You have an untrusted certificate.

Ok, how can we get this running in a slightly better way? I want:

  • A friendly machine name, not localhost.
  • People to be able to talk to my instance of IIS Express from the outside.
  • Actual SSL over port 443.
  • My ASP.NET application to switch between SSL and not automatically when I'm logging in.
  • My self-signed certificate to be trusted so I don't get warnings.
  • To use PowerShell at some point for no reason at all because that's bad-ass.

Here we go.

The Hard Ninja Way - Local SSL over 443 with IIS Express and the Gracious Manatee that is The Command Line

These steps may seem a little scary, but it's useful to know that they are happening (or have happened) already to make the Easy Way work for you. I'll show you how to do it yourself, then I'll show you an undocumented way to make part of The Hard Way even easier. It's important to know what's happening though and why when you start running random commands from an Administrator Command Prompt, right?

1. Getting IIS Express to serve externally over Port 80

My machine is called HANSELMAN-W500, so I'll use that name. You could update your hosts file and use a friendly name. To start, use your computer name. if you don't know the name of your computer, you're silly. Go to the command prompt and type "HOSTNAME" to find out.

First, we need to tell HTTP.SYS at the kernel level that it's OK to let everyone talk to this URL by making an "Url Reservation." From an administrative command prompt:

netsh http add urlacl url=http://hanselman-w500:80/ user=everyone

Next, as I want to be able to talk to IIS Express from outside (folks on my network, etc. Not just localhost) then I need to allow IIS Express through the Windows Firewall. I can do that graphically from Windows, or type:

netsh firewall add portopening TCP 80 IISExpressWeb enable ALL

Finally, I need to make sure that my project will use Port 80. I can do that one of two ways. I can either edit the applicationHost.config manually and add the binding (my recommended way):

<site name="MvcApplication18" id="39">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="c:\users\scottha\documents\visual studio 2010\Projects\MvcApplication18\MvcApplication18" />
<binding protocol="http" bindingInformation="*:15408:localhost" />
<binding protocol="https" bindingInformation="*:44302:localhost" />
<binding protocol="http" bindingInformation="*:80:hanselman-w500" />

Or, I can do that from the command line too! Although it's a little scary. I can confirm my changes in ApplicationHost.config though if I mess up.

"c:\Program Files (x86)\IIS Express\appcmd.exe" set site / /+bindings.[protocol='http',bindingInformation='*:80:hanselman-w500']

Notice that I'm using the appcmd.exe that came with IIS Express. I don't want to mess up my actual IIS installation if I have one.

2. Making an SSL Cert, hooking it up to IIS Express and making it Trusted

Let's make a SSL certificate of our own. Note the CN=. I'm making it my Computer Name, but you could make it or whatever makes you happy. It should line up with whatever name you've been using so far.

makecert -r -pe -n "CN=HANSELMAN-W500" -b 01/01/2000 -e 01/01/2036 -eku -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

Now, a tricky part. Go find this certificate in the Certificate Manager. Run MMC.exe, go File | Add/Remove Snap In, then select Certificates. Pick the Computer Account. (This is why you can't just run certmgr.msc) and add it.

Adding a Computer Cert

It'll likely be the certificate with an expiration data of 1/1/2036 under Personal Certificates. Double click on your certificate. Go to Details, and scroll down to Thumbprint. Copy that into the clipboard, as that identifies our new certificate.

Console1 - [Console Root_Certificates (Local Computer)_Personal_Certificates] (68)

Remove all the spaces from that Thumbprint hash. You can remove those spaces with Notepad if you're Phil Haack, or in PowerShell if you're awesome:

C:\>"41 d8 50 95 11 0e 1d f6 8c 89 84 97 55 25 a8 60 59 35 23 0a" -replace " "

Take the hash and plug it in to the end of THIS command:

netsh http add sslcert ipport= appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=YOURCERTHASHHERE

The AppId doesn't really matter, its just a GUID. This tells HTTP.SYS that we're using that certificate. Leave the Certificate Manager MMC running.

Now, tell HTTP.SYS that we're cool with port 443 also (we told it that 80 was cool a minute ago, remember?):

netsh http add urlacl url=https://hanselman-w500:443/ user=Everyone

Return to your applicationHost.config and add the 443 binding for your site:

<site name="MvcApplication18" id="39">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="c:\users\scottha\documents\visual studio 2010\Projects\MvcApplication18\MvcApplication18" />
<binding protocol="http" bindingInformation="*:15408:localhost" />
<binding protocol="https" bindingInformation="*:44302:localhost" />
<binding protocol="http" bindingInformation="*:80:hanselman-w500" />
<binding protocol="https" bindingInformation="*:443:hanselman-w500" />

If I say "Show All Sites" from the IIS Express tray icon, I'll see my site(s) and the URLs they are bound to.

IIS Express (73)

Now I can visit https://hanselman-w500, but again I get a certificate error.

Certificate Error

Go back to the CertMgr MMC, and drag your self-signed SSL Certificate from Personal into Trusted Root Certificates.

Move my cert into trusted certs

Suddenly my local SSD site is legit! Very cool.

No more certificate error

3. Getting ASP.NET to force SSL with an URL Rewrite Rule

One of the things Cassini (Visual Studio Web Developer Server) can't do is UrlRewriting. I want my app to force SSL when I hit /account/logon or /account/register. I'll add this to the first node of system.webServer in my app's web.config:

<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="^account/logon$|^account/register$" />
<add input="{HTTPS}" pattern="^OFF$" />
<action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />

I could also use the RequireHttps attribute on my controllers if I like.

Appendix Z: A totally undocumented way to make part of this easier that you use at your own risk

There's a command line helper deep inside of the IIS Express directory that I never mentioned to you. We never spoke! I don't know you. Who is this? Stop calling! ;)

C:\Program Files (x86)\IIS Express>IisExpressAdminCmd.exe
Usage: iisexpressadmincmd.exe <command> <parameters>
Supported commands:
setupFriendlyHostnameUrl -url:<url>
deleteFriendlyHostnameUrl -url:<url>
setupUrl -url:<url>
deleteUrl -url:<url>
setupSslUrl -url:<url> -CertHash:<value>
setupSslUrl -url:<url> -UseSelfSigned
deleteSslUrl -url:<url>

1) Configure "http.sys" and "hosts" file for friendly hostname "contoso":
iisexpressadmincmd setupFriendlyHostnameUrl -url:http://contoso:80/
2) Remove "http.sys" configuration and "hosts" file entry for the friendly
hostname "contoso":
iisexpressadmincmd deleteFriendlyHostnameUrl -url:http://contoso:80/

From the command line with this utility, I can quickly setup my hosts file and my HTTP.SYS Url ACLs with one command:

C:\Program Files (x86)\IIS Express>IisExpressAdminCmd.exe setupFriendlyHostnameU
rl -url:http://daddyisawesome:80/
Command 'setupFriendlyHostnameUrl' completed.

And remove them:

C:\Program Files (x86)\IIS Express>IisExpressAdminCmd.exe deleteFriendlyHostname
Url -url:http://daddyisawesome:80/
Command 'deleteFriendlyHostnameUrl' completed.

At this point you just need to update the IISExpress applicationHost.config with the correct binding. You can also use IISExpressAdminCmd setupSslUrl with SSL ports that are already reserved. However, I really think The Hard Way is best because you can really see what's going on, and you have more control.

Make It Stop!

How do I undo it all? Delete the Certificate in CertMgr, and from an Administration Console:

netsh http delete sslcert ipport=
netsh http delete urlacl url=http://hanselman-w500:80/
netsh http delete urlacl url=https://hanselman-w500:443/

If you have existing SSLCerts registered with HTTP.sys, the adjust these commands.

Enjoy! Thanks to CarlosAG for his help with this post.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
April 22, 2011 3:04
Very useful post. After watching your Web Stack.. presentation I've now rolled IIS Express out at work in place of Cassini. Very surpised at how easy it was to set up, especially with the SSL on 44300 that comes with SP1.
April 22, 2011 3:05
Awesome, I'm glad!
April 22, 2011 4:09
Great post, in particular it saves me from going back through your MIX presentation and taking notes on how you did this :D
April 22, 2011 4:33
Chocotastic. Did you leave out the undocumented way to make the hard way easier? (sheesh...try parsing that one with no context...semantic web indeed...)
April 22, 2011 4:41
You might want to change the title to "... compared to Cassini". If you are already using IIS, your process is a lot more cumbersome.
April 22, 2011 5:16
Steve - More cumbersome than IIS? You'd do basically the same stuff here in IIS7, no? Or use the GUI.
April 22, 2011 5:46
Two netsh command quibbles.

It would be more secure to use something like:
    netsh http add urlacl url=http://hanselman-w500:80/ user=scott
The user value is the account allowed to listen on that URL, and since IIS Express runs under your user account that's the only user that needs to be permitted.

The 'netsh firewall' context is depreciated, you should use the current and much more complete 'advfirewall' context, like this:
    netsh advfirewall firewall add rule name="IISExpressWeb" dir=in protocol=tcp localport=80 profile=private remoteip=localsubnet action=allow
Note that this is locked down more tightly. Depending on your setup you might want to change or remove the 'profile' or 'remoteip' options, but it's better to start more secure.
April 22, 2011 9:10
Very Useful Post.

April 22, 2011 11:00
Well IISExpress is way better than Cassini, it has one major drawback. When you start debugging with Cassini a nice little icon appears in your icon bar saying that Cassini was started and is listening to port x. IISExpress does the same.

However the drawback comes when you stop debugging. Where cassini stays active, IISExpress shutdowns immediately. That's not handy when you are working on your website views and don't need to walk through your code, but only want to see how it looks..

It would be very nice if IISExpress stays active when you're done debugging.
April 22, 2011 11:48
Great post. Your video at mix was both education and entertaining. Keep up the good work.
April 22, 2011 12:04
I really enjoyed watching your sessions from mix11, Scott. And thanks for sharing the detailed post above... I know where I have to look when I need to!
April 22, 2011 12:04
another perfect useful blog post. thanks. I liked the ninja way a lot. you are the one who made me love command line :) I didn't know anything except dir command until I saw you using cmd.exe.

I am a little curious on something. on your awesome presentation at mix, it looked like Damian Edwards kind of screwed your presentation up :) but I am thinking that you once said that sometimes you are hitting an exception on purpose to get attention of the audiences (or measure their attention level). something like that I don't remember in details but the main idea is that sentence. (I might remember wrong. if so, I m sorry :S)

did u guys do that thing on purpose or it was just a momentary thing? I must also say that either way, that part was awesome ! I was clapping my hands after watching your talk and you are the way far most talented speaker on the Microsoft community.
April 22, 2011 13:11
owww, you have actually indicated that on this post;

If you watch the Mix video, you'll see towards the end where Damian Edwards educates me on this new SSL feature in VS2010SP1. I didn't know that VS2010SP1 (WebMatrix does also) installs some self-signed certificates and includes and option for turning on their use. However, as I pointed out in the video, that's only for high "strange" points like 44300+, so my more complex example still has value if you want standard port numbers

it was a real thing :) sorry for the verbosity...
April 22, 2011 13:28
Thanks Scott, I've just spent the last few days working this out - if I'd waited for your post I could have done something else!

As the Silverlight WCF client stack only supports username authentication over secure transport, the technique you describe will be really useful for anyone working in a development environment trying to call WCF services from Silverlight with basicHttpBinding while using the ASP.NET providers for authentication and authorisation. Most Silverlight approaches I've seen tend to use ASP.NET compatibility (RIA services seems to do this under the hood) which precludes using the principal-based patterns for security.

Once again, you are the master ninja!
April 22, 2011 13:54
One issue I have with this is the system-wide installation and the IIS Express config file residing under C:\Users\... I would prefer to have the full configuration + IIS express installation local to my project, is that possible? Think "automated build/test system without Visual Studio SP1 installed"...

April 22, 2011 16:26
+1 for the Pulp Fiction reference. Great post, Scott.
April 22, 2011 18:15

Nice one!
April 22, 2011 18:29
Slightly off topic, but one issue I have with IIS Express is that it always puts everything in your Home dir...which for me is mapped to a network share. This has presented certain problems. Is there anyway to make IISExpress use a local folder instead?
April 22, 2011 19:06
Hi Scott,

Nice post! As addition... two days ago I posted a tutorial on how to deal with SSL in development using the *real* IIS: Setting up a local SSL development environment for multiple sites

April 22, 2011 20:58
Nice post.

Your firewall script should use netsh advfirewall though as it is the new preferred method.

April 22, 2011 21:33
Scott, thanks for the cool walk-though. I bookmarked it for future reference.
April 23, 2011 20:39
I watched your MIX video and loved the cool stuff you demo'd. Now I'm trying to follow along with the post but...I don't have the ability to set IIS Express as default. You said "Right click on the Project in Solution and select Use IIS Express. You can also set IIS Express as the default from the Tools | Options | Projects and Solutions | Web Projects.". I created a new MVC 3 project but I don't have that right-click option. I then checked under VS2010's "Tools | Options | Projects and Solutions" menu option but I don't have Web Projects listed as an option. Instead, I see options for "General", "Build and Run", "VC++ Directories" and "VC++Project Settings". Am I missing something from the VS2010 installation? I thought I installed pretty much everything except VB.NET...? I know I also have SP1 and the MVC Tools Update so that shouldn't be the problem. I've installed IIS Express as part of WebMatrix....was I supposed to install it as a stand-alone product? The really annoying thing is that I un-installed the full-version of IIS (am running Win7 Ultimate) in order to use the light-weight IIS Express since it looked to be so much better suited for a development machine.

Any constructive suggestions would be greatly appreciated!
April 23, 2011 21:40
Please disregard my earlier comment....I just re-installed VS2010 SP1 and the "Use IIS Express by default" option show up. I've no idea what happened, really. I must have previously installed SP1 on a different machine. Anyhow, this is a PEBCAK issue. Sorry to waste your time!
April 24, 2011 12:05
Great Post.
But while executing the following statement
<netsh http add sslcert ipport= appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=YOURCERTHASHHERE>
I had put my Hash there.
It says Bad Numeric Constant : 214124.
April 24, 2011 23:49
Ishan - Try it outside PowerShell, or put ' ' around the whole appid section. That command line is confusing for PowerShell
April 26, 2011 18:43
I set this up yesterday, including a custom certificate and hooking up my website on IIS Express to port 443, and it was all working great then. But now, I come in this morning, turn on my computer and it's not working via HTTPS anymore! I can access the site via port 80 and HTTP just fine (I didn't do any UrlRewriting), and via my old SSL binding on port 44301 just fine. Very odd.

I'll try resetting everything and starting from scratch but I'm worried it'll break again when I next reboot!
April 27, 2011 18:47
Yep, came in today and my SSL site through port 443 on IIS Express isn't working again. >:[
April 28, 2011 20:41
I encountered the same problem when I tried to add the cert using netsh. Keeps giving errors on the appid, and you're right, this was due to powershell. However after adding the single quotes around it I started getting a different error.

SSL Certificate add failed, Error: 1312 A specified logon session does not exist. It may already have been terminated.

I couldn't figure out what why it was giving me this error, and looking online just kept pointing me to a MS hotfix. Turns out that because when I had encountered the problem with adding the cert using netsh, I had skipped that step to come back to it later. However because I had moved my cert already from Personal to Trusted Root Certificate Authorities, it couldn't find any certs with the certhash provided. So if anyone else has problems with this error, make sure your personal development cert is still in Personal certificate store before you use netsh to add it to the binding and move it to Trusted Root Certificate Authorities afterwards.
May 04, 2011 18:52
I am loving IIS Express! It makes so many things easier to test.

I'd like to add a suggestion for switching between HTTP and HTTPS, since Scott brought it up. Rewrite rules and the RequireHttps attribute in MVC only redirect from HTTP to HTTPS and not back to HTTP for other requests (which could save quite a bit of CPU cycles and bandwidth over time). In addition, if you happen to be running on IIS 6 and/or using Web Forms, you don't have these nice features.

I recommend taking a look at the Security Switch library. Through simple configuration in your web.config, you can setup what should be secured. The rest is assumed to be okay for access via HTTP and the module will redirect you back out of SSL automatically. It now has NuGet support now too (Install-Package SecuritySwitch).
May 05, 2011 12:49
Agree with jeroenh: I would love IIS Express if I could have all the settings in my project so I can get my project from source control and don't have to set up anything...
June 12, 2011 20:52
HI Scott,

have been playing with something similar with iphone talking to WCF via SSL, but i think this will still have the same issue that all self certs have in that unless the CA root is present on the device, for example Verisign on Iphone then you will get the same untrusted site issues on other devices.

Also there seems to be some issues with the cheaper SSL certs on the market not being able to authenticate due to key chain access and walking the tree to the base Cert provider

June 17, 2011 0:29
I don't get the SSL project properties (10.0.40219.1 SP1Rel). What am I missing? The only project properties I have are: "Always Start When Debugging...", "Project File", and "Project Folder".
June 17, 2011 0:31
Disregard my last. I read the instructions. :)
August 03, 2011 20:57
Hi Scott,

Thanks for the explanation. On my machine, only the 'first' seems to work over SSL, using port 44300. Any site I enable SLL for after that is not accessible, the connection is reset (or in some cases refused). I noticed IIS Express assigns the port number from a range starting at 44300, so the second site, upon enabling SSL, will be assign port 44301, and the third site 44302. No https requests are logged when the connection is reset or refused.

Any tips for troubleshooting this issue?

Thank you!
September 19, 2011 20:32
This stopped working for me the next day I came in also. I had SSL working, but now my site won't launch (SSL). Any suggestions?

IIS Express lists my SSL site in the tray, but doesn't launch when I go to the URL.
September 26, 2011 21:53
hi scott,

After following your steps I have managed to make my website work with localhost and with computername ssl was working.

But next day when I open pc ssl is not working and I repeat all the steps to configure again and then my friend wanted to see my cool mvc3 demo app so we both use hamachi vpn and as soon he hits logon page he got errors.

So now I only want my site to work with this url http://hamood-pc/Account/LogOn I don't want ssl to achieve this i did following
*using netsh i removed the binding
*remove the entries from applicationhost file
*deleted certs from MMC.exe.
*web config dont have anything related to rewrite url rules.

Now if I goto logon page using localhost it works but as soon I visit the page as http://hamood-pc/Account/LogOn it gives me sll error.

Please tell me how to disable that?
September 26, 2011 23:01
I solved my problem since it was permanent redirect browser saved that in cache when I open http://hamood-pc/ into chrome private mode website working perfectly without ssl or any https redirection.

Kudos to me
November 03, 2011 17:34
when i run the netsh command as in the example:

netsh http add sslcert ipport= appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=YOURCERTHASHHERE

using powershell or visual studio command prompt i get the following error:

The following command was not found: http add sslcert ipport= appid
={00112233-4455-6677-8899-AABBCCDDEEFF} certhash=dafebdb65ec7544218bf9a1794c6424

I am currently configuring a WCF service to use SSL and have been following from the book 'windows communcation foundation 4 - step-by-step' by john sharp.

I have visual studio 2010 SP1 and using IIS Express. The only difference I could think of is that i am running Windows XP Professional instead of Windows 7

November 13, 2011 2:00
Had to go through N tries, basically going in the dark as you can't tell from error messages what's broken and what's not. Got everything working great. The next day I come and it does't work anymore. What a POS!!!
December 15, 2011 3:17

I think by moving the self signed cert from Personal to Trusted Root CA directory causes a problem that SSL stops working after developers reboot their machines. (Don't know how it happens, but it does happen consistently.) I finally get around this issue by export and re-import the self-signed cert into the trusted root directory (instead of simply drag it over). Now my self-signed cert is considered and I don't need to REINSTALL/REPAIR IIS Express every time I reboot the machine.

You might want to update your blog post to address this issue.


Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.