Redirecting Web Traffic from HTTP to HTTPS

So I need to redirect the incoming traffic to my website so that it always uses https/SSL.

I am running IIS 7.5 on my Windows 7 machine.  I googled for “how do I make sure that all my web traffic uses https“.

The second link showing was to my web host, GoDaddy.com.  They have a page that says how to do it.  But what they didn’t tell me was how much effort I would have to go to to get it to work.

First, I had to realize that the URL Rewrite Module was an IIS plug-in and not something that comes “in the box.”  I downloaded and installed the 64-bit version.  Once installed, I could see the URL Rewrite icon in IIS Manager.
URLRewrite

Second, I added the code to my web.config file.  Here’s the code:

<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" redirectType="Permanent" 
                    url="https://{HTTP_HOST}/{R:1}" />
        </rule>   
    </rules>
</rewrite>
</system.webServer>
</configuration>

Four hours later, it works…

Here are the gotchas I ran into:

  1. Things get complicated if you try to put the redirect in a subsite.  The Rule code above must be in the web.config file in the root website.  Not a subsite.
    (I never did figure out how you might do that.  In my case, it doesn’t matter because I want my entire domain to be running in HTTPS mode.)
  2. You cannot go to the SSL Settings screen in IIS Manager and check the option to require SSL.  That option must remain unchecked to allow the HTTP traffic through so the rule can redirect it.
    SSLSettings
  3. Your website must have bindings to both HTTP and HTTPS.
    1. In IIS Manager, select the root website on the left.
    2. Next, select the Bindings option under Edit Site in the Action bar on the right.Bindings
    3. Make sure you have bindings for HTTP (typically port 80) and HTTPS (typically port 443).
  4. You do not want to mess with the HTTP Redirect option in IIS Manager.  That will not solve the original problem. The HTTP Redirect is used to forward all traffic from, say, a parked domain, to another domain entirely.
    HTTPRedirect
  5. Did I mention that the Rule code above only works at the root level of the server?   Make sure it is in the web.config at the root level, not in a virtual directory or subsite below the root.

And that’s all I have to say about that.

Oh, one more thing.  Many thanks to RUSLAN YAKUSHEV ruslany at Microsoft for his excellent documentation and blog articles about the URL Update Module.

Moving Code from the Developer’s Integration Environment to the QA Environment

When we’ve completed coding (and, if we’re feeling especially adventurous, testing said code), we promote our locally developed code to the Dev server. This serves as our integration environment. CruiseControl.Net watches our SCM for any changes promoted to the DEV branch, then it:

  1. Updates the configuration files to point to the Dev server instead of the developer’s local workstation;
  2. Builds our solution in Debug mode (for more verbose logging during the unit test runs);
  3. Runs the unit tests;
  4. Builds the solution again in Release mode;
  5. Runs the unit tests again to ensure they work in Release mode too; and
  6. Finally, publishes the necessary files to IIS.

Today, I need to figure out how much has to change to get this project onto our QA server.

The Problem

Pointing the QA environment to the QA database.

The biggest difference between the process described above and the process to move to QA is going to be changing the back end database that the solution points to. I.e. The Developer’s local workstation and the Dev server both point to the Dev database. (It’s an Oracle back end, so we do not have a separate local and server database — even if we wanted to, but I’m not sure we would.)

ORACLISM

An aside about Oracle schema ownership. As a SQL Server developer, there are several Oraclisms that confound me. I’m not sure that this is one of them, but here’s my take on it: In SQL Server, most databases are created by dbo and most tables are created as dbo. Security is then applied to users and groups to grant access to various tables. If you need to create a Dev database and a QA database for the Production database named AccountingSystemDB, you might create a new database, again as dbo, called AccountingSystemDEV and another called AccountingSystemQA. In Oracle, this notion of separate databases is superseded by a notion of separate schemas WITHIN a single database. There is no obvious corollary to dbo. The Oracle system user serves a very different purpose, perhaps relating more to the notion of sa in SQL Server. Instead, an Oracle DBA will create a Schema Owner (i.e. a user?) and then create the Schema as that owner, granting rights to that Schema to users.

For example, the Oracle Server has a single Database instance, within which, you will see three schemas named ACC_SYS_DV, ACC_SYS_QA and ACC_SYS_P. Within each schema, you will find that schema’s version of the tables. I.e. ACC_SYS_DV.ACCOUNT, ACC_SYS_QA.ACCOUNT and ACC_SYS_P.ACCOUNT. Also, a lot of database apps, use a single Application User Id to access the database, relying on the Application to implement security. (Or at least, ours does.) For each of the three environments, this Application User logs in to one of the three Schemas.

I am concerned that Entity Framework knows the Database and Schema in the connectionstring in the app.config for the ModelEF project:

 ...
 <edmKeys>
  <edmKey
   name="DataSource"
   connection="metadata=res://ModelEF/ModelEF.csdl| res://ModelEF/ModelEF.ssdl| res://ModelEF/ModelEF.msl; provider=Devart.Data.Oracle; provider connection string=" User Id=APPDV; Password=*****; Server=devTns.world; Home=oraodac11g_home1;Persist Security Info=True""
   containerName="ModelEF.Entities">
   ...
  </edmKey>
  ...
 </edmKeys>
</ideablade.configuration>

Above we see the Oracle server instance devTns.world, and the Dev database schema owner APPDV. There is also a Home= entry pointing to the developer’s OraHome that needs to be removed.

EF then maps the Schema owner into the EDML (EDMX) file:

...<EntitySet
  Name="ACCOUNTs"
  EntityType="ModelEF.Store.ACCOUNT"
  store:Type="Tables"
  Schema="APPDV" <=NOTICE DV SCHEMA OWNER IS HERE
  Table="ACCOUNT" />...

If this was a SQL Server solution, the schema owner would be the same (whether it is dbo or not) in the AccountingSystemDEV and AccountingSystemQA databases. In Oracle, this is not the case, so I am curious if I will need to update the Schema tag in the EDML (EDMX) . If so, the promotion to QA will force a rebuild, not just a reconfigure.

The Ideablade configuration also knows the Database and Schema in the connection attribute of the edmKey tag in the Model project’s app.config and in the web host project’s web.config:

<configuration>
 <connectionStrings>
  <add name="Model.EFConnectionString"
   connectionString="metadata=res://*/ModelEF.csdl| res://*/ModelEF.ssdl| res://*/ModelEF.msl; provider=Devart.Data.Oracle; provider connection string=&quot; User Id=APPDV; Password=*****; Server=devTns.world; Home=oraodac11g_home1; Persist Security Info=True&quot;"
   providerName="System.Data.EntityClient" />
 </connectionStrings>
</configuration>

[It turns out, I do need to change the tags, change the connection strings, and regenerate the pregenerated views.]

A SOLUTION

Since we are using CruiseControl.Net (CCNet) for our automated build, and since we are using Nant for some of the less “build-ish” and more “configure-ish” tasks, I was able to add a Nant task in the CCNet project configuration that does a string replace in all the EDML (EDMX) and .config files, and then uses the T4 Template technique to recreate the Pregenerated Views.

In order to use the T4 Template attached to the ADO .Net blog, I had to make two changes because we are using Devart Entity Developer. First, the .tt file needs to be renamed from ModelEF.Views.tt to ModelEF.PregeneratedViews.tt. Second, the following line in the .tt file has to be changed:

string edmxFileName = Path.GetFileNameWithoutExtension(this.Host.TemplateFile).ToLowerInvariant().Replace(".views", "") + ".edmx";

Should be replaced with:

string edmxFileName = Path.GetFileNameWithoutExtension(this.Host.TemplateFile).ToLowerInvariant().Replace(".pregeneratedviews", "") + ".edml";

Here is the CCnet task in the CruiseControl.Net ccnet.config file to execute the Nant task:

<project name="PromoteToQA">
 ...
 <tasks>
  <nant>
   <buildFile>ChangesBeforeBuild-QA.build</buildFile>
   <executable>E:\Program Files\nant-0.86-beta1\bin\nant.exe</executable>
  </nant>
 </tasks>
 ...
</project>

And here is the Nant task itself:

<project name="ChangesBeforeBuild-QA" default="run">

 <target name="run">
  <call target="change Database" />
 </target> 

 <target name="change Database">
  <foreach item="File" property="filename">
   <in>
    <items>
     <include name="**/*.edml" />
     <include name="**/app.config" />
     <include name="**/web.config" />
     <include name="**/*EF.Designer.cs" />
     <include name="**/*EF.edps" />
    </items>
   </in>
   <do>
    <attrib file="${filename}" normal="true" />
    <loadfile file="${filename}"
     property="file.textContent">
     <filterchain>
      <replacestring from="APPDV" to="APPQA" ignorecase="true"/>
      <replacestring from="*****" to="*****" />
      <replacestring from="devTns.world" to="qaTns.world" ignorecase="true"/>
      <replacestring from="Home=oraodac11g_home1;" to="" />
     </filterchain>
    </loadfile>
    <echo message="Writing Database Change to: ${filename}" />
    <echo file="${filename}">${file.textContent}</echo>
   </do>
  </foreach>
 </target>
 
 <target name="Recreate Precompiled Views Files">
  <!-- unlock the view files -->
  <foreach item="File" property="filename">
   <in>
    <items>
     <include name="**/*.PregeneratedViews.cs" />
    </items>
   </in>
   <do>
    <attrib file="${filename}" normal="true" />
   </do>
  </foreach>
  <!-- transform the *.PregeneratedViews.tt files to recreate the *.PregeneratedViews.cs files -->
  <foreach item="File" property="filename">
   <in>
    <items>
     <include name="**/*.PregeneratedViews.tt" />
    </items>
   </in>
   <do>
    <echo message="Transforming: ${filename}" />
    <exec program="dependencies\TextTransform\TextTransform.exe">
     <arg value="${filename}"/>
    </exec>
   </do>
  </foreach>
 </target>
 
</project>

And that’s it. Before CruiseControl.net starts running the actual tasks, it runs this Nant task to prepare the source files for the QA environment.

Opening Salvo: Planning your SCM for a Silverlight project

One of the easiest decisions to make when embarking on a Silverlight development adventure, is to decide to use a Source Code Manager (SCM) to keep the myriad projects and files organized.

I shall leave it up to you to decide which SCM to use.

As far as setting up the SCM environment, there are treatises elsewhere (I hope) on the philosophical disagreement on setting up releases, branches and code progression paths in SCM.

As for me and my house, we have standardized on a very small implementation of SCM philosophy.

First, with regard to promotion and versions:

  1. The Production code is the Top level Branch.
  2. Below that is the Staging code (for us, Staging is where real users do testing).
  3. Below Staging is the QA code (QA is where certain  designated project testers do testing).
  4. Below QA is the Dev code (Dev represents the latest version of the code that has been promoted from each of the developers.  This is used for integration and unit testing, and is the place where developers test their contributions after they have finished their local coding/testing effort.  There is an automated build process that builds, tests and deploys (if build is successful) the compiled project to the Dev server for integration testing.
  5. Below the Dev code are the individual workspaces for each developer.  Each developer can create workspaces off the Dev branch.  They are free to make their changes in their workspaces, and their changes are isolated from:
    a) the integration build on the Dev server;
    b) other developer’s “work in process”; and
    c) their own experiments and “not for this release” changes.
  6. Code is promoted from each developer’s workspace to the main Dev branch.  It is then occasionally promoted from the Dev branch to QA for testing.  When it passes it is promoted to Staging for testing.  When that passes the code is promoted to Production on the release schedule.For example:
    SCM Example

Second, with regard to tools and dependencies:

  1. In the DV branch, there is a folder called Installations, where we keep the installers for all of the tools we use.  This serves two purposes: a) it centralizes the installs so rebuilding a dev environment is not such a chore; b) it makes sure that all the dev environments are using the same versions of the same tools.  We have also checked in a readme.txt for each tool documenting our licenses, download locations, vendor logins, etc., needed to obtain the file from its source or to get updates.  This folder is then “cloaked” in our SCM to ensure that it is not promoted up to the QA branch.  Developers can cloak it in their branch once they have installed everything and configured their environment so that they can delete the install files and reclaim that space.

    Installations Folder example

  2. In the DV branch there is a folder called Dependencies, where we keep all the DLL’s and third party references.  All projects in the solution(s) then reference the DLL’s from the Dependencies folder, and NOT from their local Program Files installation of the tool in question.  This serves two purposes:  a) it ensures that, regardless of which version of which tool is installed locally, that all of the DLL’s required to compile the app are in SCM and are in a folder that has the same relative path (i.e. ..\dependencies) on every developer’s hard drive.   This avoids so many seemingly random errors that crop up when a developer links a project to their own Program Files menu.  NOTE:  This pretty much invalidates the use of “Add Reference, Select from List” for all but the core MS DLL’s, as you will almost always have to pick “Add Reference, Browse” to get the reference to point to the Dependencies folder.  It also means that most project creation wizards will produce a project that you then have to remove and recreate the references in so that they point to the Dependencies folder that the wizard knew nothing about.In our projects, DLL’s from: C:\Program Files\Reference Assemblies and C:\WINDOWS\Microsoft.NET, are referenced from those locations, all other DLL’s are referenced from the copies stored in the Dependencies folder.  For example, the C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries folders are copied over to the Dependencies\Silverlight\Libraries folder.

    Dependencies Folder example.