New Workstations and IIS7 configuration Our new workstations don’t have IIS6 anymore and they are configured to work with IIS Express (stripped down version of IIS7). Because of the new IIS and different permission settings (we don’t have administrator permissions to workstations), we need to setup and debug websites different way. Special thanks to Kyle for helping with IIS7 settings! Steps below describe changes that need to be made to run sites on IIS Express. They apply to sites that run on .NET Framework 4.0, .NET Framework 3.5 and .NET Framework 2.0 and they apply to Visual Studio 2010, Visual Studio 2008 and Visual Studio 2008 I am describing the process once - depending on the version of the Visual Studio you use, you may see slightly different user interface, but the concept is the same. Important: Many of our live sites are configured to run on IIS6 – please DON’T push the web.config changes to the production/design server if they run on IIS6. That should not be an issue with new sites, because they are configured on IIS7. Also, most of the e-commerce design sites will be moved to IIS7 soon. The main difference between IIS6 and IIS7 is that IIS7 allows to run in the “integrated mode” – that means that every request to the IIS is routed via ASP.NET, regardless of the extension. In other words, all extensions (.jpg, .gif, .xml, .js) are mapped with .NET by default. Because of that we don’t need ISAPI Rewrite anymore and that software is not installed on our new workstations. The same rewrite functionality that was defined in the httpd.ini file is configured now in the web.config – this is one of the reasons, why we can’t push the web.config changes to the servers that run on IIS6 If you have any questions related with running/testing/debugging sites on new workstations with IIS Express, please talk to your Technical Manager. All Technical Managers are familiar with the steps below and have been testing IIS Express already. Setting up your new workstation to enable project development with IIS Express. The following URL values may also be useful if you encounter any project specific issues. http://learn.iis.net/page.aspx/860/iis-express/ http://www.iis.net/ConfigReference IISExpress is the same as IIS7 and it uses the same configuration files, but there is no GUI interface with IISExpress and configuration is updated directly through files. There are mainly 2 files that we need to update: 1) C:\Users\<your_login>\Documents\IISExpress\config\ When you look at the path name in the path will appear as “My Documents”: 2) web.config of the website that you are working on Configuration File and VS 2010/VS2008/VS2005 1. After downloading your project, right click the web project and select ‘Properties’. Set the start options similar to those below. Ensure all the ‘Debuggers’ items are unchecked, and that the command line argument is a value specific to your project (keep this value noted for a later step) 2. Run the IIS Express icon your desktop for the first time. Once loaded, select the ‘Q’ option to end the process. This will have created the initial configuration files, which you can find inside the C:\Users\<your_login>\Documents\IISExpress\config\ folder 3. Open the C:\users\<your_login>\Documents\IISExpress\config\applicationhost.config and find the element <sites> in that file Inside that elements you should see one site configured there by default with the name=”Website1” - you can remove the whole <site> element – we will configure a new one for our site. After removing the <site>…</site> content, please paste the code below at the same location: <site name="GarretPopcorn" id="1"> <application path="/"> <virtualDirectory path="/" physicalPath="C:\inetpub\wwwroot\Standards40\web\" /> <virtualDirectory path="/cms" physicalPath="\\pr-stand4vwb01\wwwroot\standards40.com\cms" /> <virtualDirectory path="/assets" physicalPath="\\pr-stand4vwb01\wwwroot\standards40.com\assets\" /> <virtualDirectory path="/ckeditor" physicalPath="\\pr-stand4vwb01\wwwroot\standards40.com\CKEditor\" /> </application> <bindings> <binding protocol="http" bindingInformation="*:80:localhost"/> </bindings> <applicationDefaults applicationPool="Clr2IntegratedAppPool" /> </site> Important notes about the code above: 1) New sites in the future will be configured the same way - we will just keep adding new <site> elements to the configuration file 2) Please note that the id and name values need to be unique for each site that you configure – the name parameter is referenced from the Visual Studio in the command line arguments (see screen shot above, /site:GarretPopcorn) 3) Virtual directories are configured in the applicationhost.config file as well – you can have as many virtual folders as you wish – in a example above, I used only 3 virtual directories 4) Please notice that I also added virtual directory path to the root of the site on my localhost – we need to keep that line for each website we setup in the configuration file <virtualDirectory path="/" physicalPath="C:\inetpub\wwwroot\Standards40\web\" /> 5) Please use Clr2IntegratedAppPool websites that run on Framework 2.0 or 3.5 and use Clr4IntegratedAppPool for websites that run on .NET Framework 4.0 These are the only changes that you need to make to the configuration file inside C:\users\<your_login>\Documents\IISExpress\config\ folder – remaining changes are in the web.config and source code. Programming Changes 1) Change to the \common\RegExUrlMapping\RegExUrlMappingModule.vb file Private Function MapPath(ByVal path As String) As String 'Format the requested page (url) to have a ~ instead of the virtual path of the app Dim appVirtualPath As String = HttpContext.Current.Request.ApplicationPath If path.Length >= appVirtualPath.Length Then If path.Substring(0, appVirtualPath.Length).ToLower = appVirtualPath.ToLower Then path = path.Substring(appVirtualPath.Length) If path.Length > 0 AndAlso path.Substring(0, 1) = "/" Then path = "~" & path Else path = "~/" & path End If End If End If Return path End Function That change has been posted to the Share Point in the past and it was related with sites being hosted on IIS7. If you work on a website that is based on the latest standards, this change will be applied already. 2) All new workstations use IPv6 local IP address notation and when we check the HOSTS variable, we get the IP address that is not returning any matches from the lookup table in the IP2Country web service. That issue occurs only when we run sites from localhost and the fix below turns off the IP country check from workstations. File: \App_Code\AdminLoginPage.vb – change is marked in yellow below Public Shared Function ValidateLoginCountry(ByVal DB As Database) As Boolean If CBool(SysParam.GetValue(DB, "AdminLoginCountryEnabled")) AndAlso Not HttpContext.Current.Request.Url.IsLoopback Then … <body of the function is here> … End If Return True End Function Web.config changes In order to run the website in the integrated mode, we need to change the configuration and move the content of the 2 elements that are not allowed anymore (don’t delete it yet, keep reading…) <httpHandlers> <httpModules> There is a new section in the web.cofng that is only used by IIS7 – that new section is <system.webServer> and it must be created at the same level as <system.web>. I created that new section right above <system.web> tag. Inside system.webServer, we need to configure: 1) <modules> – that section contains the same elements as the httpModules 2) <handlers> - that section contains the same elements as httpHandlers 3) <rewrite> - that section contains rewrite rules that previously were handled by ISAPI rewrite. Note: If your project contains httpd.ini file and uses ISAPI rewrite, please keep it. That file is going to be ignored by IIS Express, but we need to keep it in VSS / TFS for consistency, because that file may/is used by the live site (please remember that most of our sites are still running on IIS6) Below are the steps for changing the web.config: 1) Copy following tags right above <system.web> tag <system.webServer> <modules> </modules> <handlers> </handlers> <rewrite> <rules> <rule name="site map" stopProcessing="true"> <match url="sitemap\.xml" /> <action type="Rewrite" url="/sitemap.aspx"></action> </rule> <rule name="append slash" stopProcessing="false"> <match url="^([^.?]+[^.?/])$" ignoreCase="true"></match> <action type="Redirect" redirectType="Permanent" url="{R:1}/"></action> </rule> <rule name="remove default.aspx" stopProcessing="false"> <match url="^(.*)/default.aspx" ignoreCase="true" /> <conditions> <add input="{URL}" pattern="^/admin/(.*)" negate="true" ignoreCase="true" /> </conditions> <action type="Redirect" redirectType="Permanent" url="{R:1}/"></action> </rule> <rule name="add default.aspx for admin" stopProcessing="false"> <match url="admin/(.*)/$" ignoreCase="true" /> <action type="Redirect" redirectType="Permanent" url="/admin/{R:1}/default.aspx"></action> </rule> </rules> </rewrite> </system.webServer> The rewrite section contains rules that were defined in the httpd.ini file The first one redirects request to sitemap.xml file to sitemap.aspx Second one appends slash to URLs that didn’t have slash, i.e. /news URL will be redirected to /news/ Third one removes the default.aspx from all URLs on the front end If there are other rules implemented on your site that runs on IIS6 and the httpd.ini file was customized, you will need to add the same rules to the <rules> section to keep the local site working consistent with a live site that runs on IIS6 2) In the previous steps we copied tags for modules and handlers, but these tags were empty. You will need to copy the content from <httpModules> and <httpHandlers> sections inside these empty tags. After you copy the content, you can remove <httpModules> and <httpHandlers> tags completely Notes: There are 2 lines in the <httpHandlers> section that need to be removed (instead of copied to the <handlers> section, otherwise you will get an error: <add path="*.asp" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True"/> <remove verb="*" path="*.asmx"/> Additionally, after you copy all elements you will need to add a name attribute for each line (the name property is required) – it doesn’t really matter what name you will use as long as the names are unique Example: <add verb="POST,GET" path="FileMerge.axd" name="name4" type="FileMerge, Common"/> Remove validate tags if necessary when copying to <httpHandlers> Sites using framework 2.0 and 3.5 may throw an error related with missing Session State Module. If you get an error, you will need to add following lines to the <modules> section <remove name="Session" /> <add name="Session" type="System.Web.SessionState.SessionStateModule" /> 3) Open your projects web.config file and location the <compilation> element. Change the element to include the tempDirectory attribute as shown below: <compilation debug="true" strict="False" explicit="True" tempDirectory="C:\Inetpub\Temp\GarrettPopcorn\"> If you are running site on .NET framework 4.0, please us following tag <compilation debug="true" strict="False" explicit="True" targetFramework="4.0" tempDirectory="C:\Inetpub\Temp\GarrettPopcorn\"> 4) Registry keys need to go into this location since the workstations are now 64 bit. [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Websites\] 5) If your tasks.exe file is using special Excel driver that runs only on 32-bit machines, you will need to change the build configuration for tasks.exe to 32-bit Also, under properties of the “Tasks” project, select “Compile” then change the Build output path to remove the “x86” so it is just “bin\Debug\” This change is NOT required if your site doesn’t use 32-bit driver for Excel file export/import Important Changes above apply for older sites that require 32-bit driver for Excel. All new websites that need to read/write data from Excel files need to be programmed using following library: http://epplus.codeplex.com/ That library is solid, stable and has been tested already on idev mail 2.0 and idev search 2.0 Other issues / tips 1) Skype & Port 80 (Thanks Kyle!) A few of us ran into an issue where I couldn’t start IISExpress and isolated the problem to Skype. You may wish to uncheck this feature “Use port 80 and 443 as alternatives for incoming connections” inside Skype if you use it to prevent a similar occurrence. Also, a handy trick is on this post below to isolate which process/application is using a particular port # on your workstation. No administrator privileges necessary: http://www.kindawannadothat.com/2009/04/how-to-find-out-which-application-is-using-whatport-windows/ 2) Shortcut to pre-defined websites A handy shortcut that was suggested at the programming committee meeting (thanks to Levente/Ali) is to create a folder that contains your IIS shortcuts. You just do one shortcut for each site you have in the config. Further, you can create a new “Toolbar” by right clicking on the task bar and selecting “New Toolbar” Once you select new Toolbar, you can specify the folder that contains each of your shortcuts. This will present your shortcuts as a list of options (see the IISExpress text in the screenshot above). If you want to change it to remove the icon, or remove the text “IISExpress”, you can unlock the task bar, then right click on the dotted line next to it to set those options. 3) Macro to attach debugger to IIS Express process (Thanks Levente!) You can create a macro with this code in the macroeditor (ALT+F11) you can overwrite the module1 if you want: Imports Imports Imports Imports Imports System EnvDTE EnvDTE80 EnvDTE90 System.Diagnostics Public Module AttachToProcess Sub IISExpress() For Each process As EnvDTE.Process In DTE.Debugger.LocalProcesses If (process.Name.IndexOf("iisexpress.exe") <> -1) Then process.Attach() Exit Sub End If Next End Sub End Module And associate to a keyboard shortcut under Tools->Options->Environment->Keyboard type in your macro name in the show command containing and add a shortcut key in press shortcut key (even F5 if you want) and this will attach it to the IIS express process. I also have a macro for collapse all items in the solution explorer is someone is interested. 4) Setup multi-site test environment on localhost In order to setup multi-site environment on localhost you will need to change the C:\Windows\System32\drivers\host file (same was as we did before) and you will need to add new bindings in the C:\users\<your_login>\Documents\IISExpress\config\applicationhost.config file as well. Please see example below applicationhost.config <site name="idevSearch" id="2"> <application path="/"> <virtualDirectory path="/" physicalPath="C:\inetpub\idev.search\SaaS\web\" /> <virtualDirectory path="/tmp" physicalPath="C:\inetpub\idev.search\SaaS\tmp\" /> <virtualDirectory path="/assets" physicalPath="C:\inetpub\idev.search\SaaS\assets\" /> </application> <bindings> <binding protocol="http" bindingInformation="*:80:localhost" /> <binding protocol="http" bindingInformation="*:80:search.blaircandy.com" /> <binding protocol="http" bindingInformation="*:80:idevsearchpreview.americaneagle.com" /> </bindings> <applicationDefaults applicationPool="Clr4IntegratedAppPool" /> </site> hosts 127.0.0.1 127.0.0.1 search.blaircandy.com idevsearch-preview.americaneagle.com